匹配CL-PPCRE的行尾

Sun*_*der 3 regex common-lisp cl-ppcre

我有一个相当简单的正则表达式,在我的Ruby代码中运行得非常好,但拒绝使用我的Lisp代码.我只是想匹配一个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
Run Code Online (Sandbox Code Playgroud)

有人可以帮忙吗?

han*_*s23 9

默认情况下,反斜杠(\)字符是单个转义字符:它阻止对其后面的字符进行任何特殊处理,因此它可以用于"在字符串文字中包含双引号()"\"".

因此,当你通过文字串"^/\w*$"cl-ppcre:scan,传递的实际字符串会"^/w*$",即反斜杠只会被删除.您可以通过评估来验证这一点(cl-ppcre:scan "^/\w*$" "/w"),它将匹配.

为了在你的正则表达式的反斜杠字符,你需要引用它,像这样:"^/\\w*$".

如果你使用文字正则表达式,所需的字符串引用可能变得乏味且难以阅读.看一下CL-INTERPOL的库,它为Lisp阅读器添加了一个更好的正则表达式语法.


cor*_*ump 6

如果您对正则表达式有疑问,还可以使用以下命令进行检查ppcre:parse-string

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

返回值是表示正则表达式的树。事实上,您可以在 CL-PPCRE 需要正则表达式的任何地方使用相同的表示形式。上面告诉我们反斜杠-w被解释为文字w字符。

将其与您想要使用的表达式进行比较:

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

尽管它有点冗长,但树表示有助于将值组合到正则表达式中,而不必担心字符串内嵌套字符串或特殊字符。例如,这里的正则表达式在使用之前在函数中进行计算,而不必转义特殊字符:

(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))))))
Run Code Online (Sandbox Code Playgroud)

上面的点"."是按字面意思读取的,而不是作为正则表达式读取。这意味着您可以在纯字符串正则表达式中使用转义字符来匹配诸如"(^.^)"或 之类的"[]"难以写入和读取的字符串。您可以使用表达式将正则表达式作为字符串使用(:regex "...")

CL-PPCRE 有一项优化,即在加载时使用load-time-value. 如果您的正则表达式不是简单的常量,则可能不会应用该优化,因此您可能希望将自己的扫描器包装在load-time-value表单中。只需确保在加载时准备好足够的定义,例如辅助maybe函数。