Соответствие конца строки с 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
функция.