Чому регулярні вирази, створені за допомогою конструктора regex, використовують синтаксис, відмінний від інтерактивних регулярних виразів?


26

Отже, використовуючи звичайний конструктор виразів (Mx re-builder), знаходження рядків, які закінчуються на \ займає "\\ $", а при пошуку та заміні регулярними виразами займає лише "\ $". Я б очікував, що конструктор регулярних виразів створить прямо придатні вирази, так що ж пояснює цю різницю?


6
Він будує вирази, які можна використовувати в коді.
або-або

1
@ Або-Або Це відповідь, яку я шукав, я не розумів, що є різниця між тим, що можна використовувати в коді, і тим, що можна використовувати в інтерфейсі. Здається протилежним інтуїтивно зрозумілим, що реконструктор використовує синтаксис кодів, а посібник не говорить, але це пояснює різницю.
користувач2699

2
Для того, щоб зробити конструктор regex більш корисним для складання інтерактивних пошуків, перегляньте сторінку вікі 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 підкаже вам інтерактивно.

Якщо ви хочете використовувати синтаксис рядків за замовчуванням, додайте наступне у свій файл init або використовуйте M-x customize-option RET reb-re-syntax RET

(setq reb-re-syntax 'string)

Зауважте, що ви можете перемикатися між синтаксисом читання та рядка під час редагування регулярного вираження без втрати даних. Ви також можете переключитися з сексових форм на синтаксис читання / рядка (природно; для цих бібліотек є компіляція сексорів до рядків), але ви не можете піти в іншому напрямку та генерувати секпс із рядка. реконструктор пам’ятає, яким був сексп, тому ви не втрачаєте такої форми, змінюючи синтаксис; але він також не оновлюється, якщо змінити регулярний вираз в іншому синтаксисі, а потім змінити назад. Коротше кажучи, якщо ви будуєте регулярний параметр як 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синтаксисі, а також для інших.

Або щоб включити підказку для rxvs rx-to-stringgotcha, описану вище, вкажіть рядок режиму "Regexp [rx-to-string]" при використанні 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))))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.