转义字符(反斜杠)仅转义自身和双引号(§2.4.5 Double-Quote):
如果看到单个转义字符,则丢弃单个转义字符,累积下一个字符,并继续累积。
这意味着:
"\[([a-zA-Z0-9_-]+)]"
解析与以下相同,其中不存在反斜杠:
"[([a-zA-Z0-9_-]+)]"
CL-PPCRE 实现的 PCRE 语法将左方括号理解为字符类的特殊语法,并在下一个右方括号处结束。因此,上面将以下内容视为一个类:
[([a-zA-Z0-9_-]
对应的正则表达式树是:
CL-USER> (ppcre:parse-string "[([a-zA-Z0-9_-]")
(:CHAR-CLASS #\( #\[ (:RANGE #\a #\z) (:RANGE #\A #\Z) (:RANGE #\0 #\9) #\_ #\-)
特别注意,它里面的左括号是按字面意思处理的。当解析器遇到上述片段后面的右括号时,它会将其解释为寄存器组的结尾,但没有启动这样的组,因此在字符串的第 16 位出现错误消息。
为避免将括号视为字符类,它必须在字符串中以文字反斜杠开头,就像您尝试做的那样,但为了这样做,您必须编写两个反斜杠字符:
CL-USER> (ppcre:parse-string "\\[([a-zA-Z0-9_-]+)]")
(:SEQUENCE #\[
(:REGISTER
(:GREEDY-REPETITION 1 NIL
(:CHAR-CLASS (:RANGE #\a #\z) (:RANGE #\A #\Z) (:RANGE #\0 #\9) #\_ #\-)))
#\])
右方括号不需要反斜杠。
我鼓励您使用树形形式在 Lisp 中编写正则表达式,并:regex
在提高清晰度时使用术语:它避免了必须处理转义带来的那种问题。例如:
CL-USER> (ppcre:scan-to-strings
'(:sequence "[" (:register (:regex "[a-zA-Z0-9_-]+")) "]")
"[has-instance]")
"[has-instance]"
#("has-instance")