Почему регулярные выражения, созданные с помощью построителя регулярных выражений, используют синтаксис, отличный от интерактивных регулярных выражений?

26

Таким образом, используя построитель регулярных выражений (Mx re-builder), для поиска строк, заканчивающихся на \, требуется «\\ $», а при поиске и замене на регулярное выражение - только «\ $». Я ожидал бы, что построитель регулярных выражений создаст непосредственно используемые выражения, так что же объясняет эту разницу?

user2699
источник
6
Он строит выражения, непосредственно используемые в коде.
abo-abo
1
@ abo-abo Это ответ, который я искал, я не осознавал, что есть разница между тем, что можно использовать в коде, и тем, что можно использовать в пользовательском интерфейсе. Кажется нелогичным, что в пересборщике используется синтаксис кодов, а в руководстве ничего не сказано, но это объясняет разницу.
user2699
2
Чтобы сделать построитель регулярных выражений более полезным для составления интерактивных поисков, взгляните на вики-страницу ReBuilder emacs , особенно на reb-query-replaceопределение функций.
Dfeich

Ответы:

29

На самом деле есть четыре различных re-builderварианта синтаксиса, и вы можете переключаться между ними с помощьюC-cTAB

Два предназначены для компиляторов регулярных выражений sexp-формы rxи sregex(но так как первый более всеобъемлющий и почти полностью совместимый с синтаксисом, вы можете действительно игнорировать sregex, если вы не работаете со старым кодом, который его использовал).

Два других варианта синтаксиса read(по умолчанию) и string(это синтаксис, который вы используете в интерактивном режиме).

readСинтаксис «код» синтаксис - то есть как признание читателя LISP - в котором вы вводите регулярное выражение в соответствии с синтаксисом чтения для строк :

C-hig (elisp) Syntax for Strings RET

stringСинтаксис (который я всегда считал излишне запутанным имя в данном контексте) является синтаксис регулярных выражений строки , которая уже была считана , и которые , следовательно , не имеет какой - либо из зарезервированных символов требуется при написании строки. То есть, это фактический синтаксис регулярных выражений, такой же, какой вы используете, когда Emacs запрашивает вас в интерактивном режиме.

Если вы хотите использовать строковый синтаксис по умолчанию, добавьте следующее в файл инициализации или используйте M-x customize-option RET reb-re-syntax RET

(setq reb-re-syntax 'string)

Обратите внимание, что вы можете переключаться между чтением и синтаксисом строк при редактировании регулярного выражения без потери данных. Вы также можете переключиться с форм sexp на синтаксис чтения / строки (естественно, для этих библиотек нужна компиляция sexps в строки), но вы не можете пойти в другом направлении и генерировать sexp из строки. re-builder помнит, какой был sexp, так что вы не потеряете эту форму при изменении синтаксиса; но он также не обновляется, если вы измените регулярное выражение в другом синтаксисе, а затем вернетесь обратно. Короче говоря, если вы создаете регулярное выражение как sexp, убедитесь, что вы редактируете его только при использовании этого синтаксиса.


Гвоздь с rxподдержкой заключается в том, что он на самом деле использует rx-to-stringфункцию, которая не совсем идентична использованию rxмакроса в коде. rxпринимает произвольное количество аргументов формы и обрабатывает их как подразумеваемую последовательность , тогда как rx-to-stringпринимает только одну форму, и любая последовательность верхнего уровня должна быть явной с '(sequence ...)или эквивалентной.

Короче говоря, когда вы вводите форму '(...)в перестроителе, она обрабатывается как (rx-to-string '(...))и не(rx ...)

Также обратите внимание, что неправильная форма может привести re-builderк прекращению динамического обновления совпадений в связанном буфере, даже после того, как форма снова станет действительной. C-cC-uСвязывания для reb-force-updateполезен для разрешения этих ситуаций.


По умолчанию строка режима показывает «RE Builder» при использовании readили stringсинтаксис и «RE Builder Lisp» при использовании rxили sregexсинтаксис, но кажется гораздо более полезным определить конкретный используемый синтаксис (особенно для различия между readи string).

Если вы устанавливаете delightпакет из GNU ELPA, вы можете использовать следующее, чтобы добавить индикатор синтаксиса в строку режима.

(let ((name '("Regexp[" (:eval (symbol-name reb-re-syntax)) "]")))
  (delight `((reb-mode ,name :major)
             (reb-lisp-mode ,name :major))))

Это изменяет имя режима на «Regexp [read]» в readсинтаксисе, а также для остальных.

Или включить подсказку для rxпротив rx-to-stringGotcha описано выше, сделать режим линии скажет «Regexp [ге к строке]» при использовании rxсинтаксиса:

(let ((name '("Regexp["
              (:eval (symbol-name (if (eq reb-re-syntax 'rx)
                                      'rx-to-string
                                    reb-re-syntax)))
              "]")))
  (delight `((reb-mode ,name :major)
             (reb-lisp-mode ,name :major))))
Phils
источник