ANSI Common Lisp 并不支持正则表达式,但是也有第三方库,如:cl-ppcre。
同时也可以到 Cliki:regexp 上了解更多的知识。
注意,有些解释其默认是实现了正则表达式的,尤其是 CLISP 和 ALLEGRO CL 具体的可以查阅相关的解释器的文档。
PPCRE
使用 PPCRE 库
CL-PPCRE,全称为 Portable Perl-compatible regular expressions。是个性能比较好的库,可以通过 Quicklisp 来调用:
(ql:quickload :cl-ppcre)
(use-package :cl-ppcre)
寻找匹配项
scan
(let ((ptrn (ppcre:create-scanner "(a)*b")))
(ppcre:scan ptrn "xaaabd"))
等效于
(ppcre:scan "(a)*b" "xaaabd")
但是第一种的方法需要的时间更少,而且只会在编译时对表达式进行解析。
提取信息
CL-PPCRE 有多种提取信息的方法,其中最常用的是:scan-to-strings
和 register-groups-bind
。其中 scan-to-strings
与 scan
类似,只不过返回的是匹配到的字符串,而不是位置。register-groups-bind
可以将匹配到的字符串给绑定到相对应的变量上,如下:
(ppcre:register-groups-bind (first second third fourth)
("((a)|(b)|(c)+" "abababc" :sharedp t)
(list first second third fourth))
;; => ("c" "a" "b" "c")
CL-PPCRE 也可以在对匹配的项调用函数,然后再把函数处理后的结果赋给最后的返回结果
(ppcre:register-groups-bind (fname lname (#'parse-integer date month year))
("(\\w+)\\s+(\\w+)\\s+(\\d{1,2})\\.(\\d{1,2})\\.(\\d{4})" "Frank Zappa 21.12.1940")
(list fname lname (encode-universal-time 0 0 0 date month year 0)))
;; => ("Frank "Zappa" 1292889600)
语法糖
当 CL-PPCRE 和 CL-INTERPOL 两个库结合使用时效果会更好。CL-INTERPOL 库可以在输入时插入 Perl,Scala 或是 Unix Shell 脚本。
在调用 CL-INTERPOL 之前,需要调用函数 enable-interpol-syntax
先进行初始化:
(interpol:enable-interpol-syntax)
更多关于语法糖的使用,参见 cl21。