Соответствие конца строки с CL-PPCRE

У меня довольно простое регулярное выражение, которое прекрасно работает в моем коде на Ruby, но отказывается работать с моим кодом на Лиспе. Я просто пытаюсь сопоставить URL (косая черта, за которой следует слово, и не более). Вот регулярное выражение, которое у меня работает в Ruby: ^\/\w*$

Я хотел бы, чтобы это соответствовало "/" или же "/foo" но нет "/foo/bar"

Я пробовал следующее:

(cl-ppcre:scan "^/\w*$" "/") ;works
(cl-ppcre:scan "^/\w*$" "/foo") ;doesn't work!
(cl-ppcre:scan "^/\w*$" "/foo/bar") ;works, ie doesn't match

Может кто-нибудь помочь?

2 ответа

Решение

Символ обратной косой черты (\) по умолчанию является единственным escape-символом: он запрещает любую специальную обработку для символа, следующего за ним, поэтому его можно использовать для включения двойной кавычки (") внутри строкового литерала, как это "\"",

Таким образом, когда вы передаете буквальную строку "^/\w*$" в cl-ppcre:scanфактическая переданная строка будет "^/w*$"то есть обратный слеш будет просто удален. Вы можете убедиться в этом, оценив (cl-ppcre:scan "^/\w*$" "/w"), который будет соответствовать.

Чтобы включить символ обратной косой черты в свое регулярное выражение, необходимо заключить его в кавычки следующим образом: "^/\\w*$",

Если вы много работаете с буквальными регулярными выражениями, то обязательное цитирование строк может стать утомительным и трудным для чтения. Взгляните на CL-INTERPOL для библиотеки, которая добавляет читателю Lisp более приятный синтаксис для регулярных выражений.

Если у вас есть сомнения по поводу вашего регулярного выражения, вы также можете проверить его с помощью ppcre:parse-string:

CL-USER> (ppcre:parse-string "^/\w*$")
(:SEQUENCE :START-ANCHOR #\/ (:GREEDY-REPETITION 0 NIL #\w) :END-ANCHOR)

Вышесказанное говорит нам, что w был интерпретирован как буквальный w персонаж.

Сравните это с выражением, которое вы хотели использовать:

CL-USER> (ppcre:parse-string "^/\\w*$")
(:SEQUENCE :START-ANCHOR #\/ (:GREEDY-REPETITION 0 NIL :WORD-CHAR-CLASS) :END-ANCHOR)

Возвращаемое значение представляет собой дерево, которое представляет регулярное выражение. Фактически вы можете использовать одно и то же представление везде, где CL-PPCRE ожидает регулярное выражение. Хотя это несколько многословно, это помогает объединять значения в регулярные выражения, не беспокоясь о вложенности строк или специальных символов внутри строк:

(defun maybe (regex)
  `(:greedy-repetition 0 1 ,regex))

(defparameter *simple-floats*
  (let ((digits '(:register (:greedy-repetition 1 nil :digit-class))))
    (ppcre:create-scanner `(:sequence
                             (:register (:regex "[+-]?"))
                             ,digits
                             ,(maybe `(:sequence "." ,digits))))))

Здесь выше точка "." читается буквально, а не как регулярное выражение. Это означает, что вы можете сопоставить строки как "(^.^)" или же "[]" это может быть трудно писать и читать с помощью экранированных символов в регулярных выражениях только для строк. Вы можете вернуться к регулярным выражениям в виде строк, используя (:regex "...") выражение.

CL-PPCRE имеет оптимизацию, где постоянные регулярные выражения предварительно вычисляются во время загрузки, используя load-time-value, Эта оптимизация может не применяться, если ваши регулярные выражения не являются тривиальными, поэтому вы можете захотеть обернуть свои собственные сканеры в load-time-value формы. Просто убедитесь, что у вас есть достаточные определения, готовые во время загрузки, такие как вспомогательные maybe функция.

Другие вопросы по тегам