更正正则表达式“ \ [([a-zA-Z0-9 _-] +)]”

时间:2020-04-29 21:55:23

标签: common-lisp cl-ppcre

以下cl-ppcre正则表达式会产生错误:

(ppcre:scan-to-strings "\[([a-zA-Z0-9_-]+)]" "[has-instance]")

debugger invoked on a CL-PPCRE:PPCRE-SYNTAX-ERROR in thread
#<THREAD "main thread" RUNNING {10010B0523}>:
  Expected end of string. at position 16 in string "[([a-zA-Z0-9_-]+)]"

我期望返回值是:

“[has-instance]”
#(“has-instance”)

以获取括号内的字符串。有人可以提供正则表达式更正吗?谢谢。

2 个答案:

答案 0 :(得分:4)

转义字符(反斜杠)仅对自身和双引号(§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")

答案 1 :(得分:0)

  1. 双击方括号即可。
  2. 您也忘记了(加倍)右括号。
(cl-ppcre:scan-to-strings "\\[([a-zA-Z0-9_-]+)\\]" "[has-instance]")
;; "[has-instance]" ;
;; #("has-instance")

对于那些不熟悉lisp的人来说,您可以使用quicklisp导入cl-ppcre

(load "~/quicklisp/setup.list") ;; adjust path to where you installed your quicklisp
(ql:quickload :cl-ppcre)