cl irregsexp - lisp-cookbook-ja/common-lisp GitHub Wiki
CLiki:cl-irregsexpでは正規表現をS式で表現します。多くの正規表現のエンジンと異なり、マッチが失敗した時点で探索が終了します。そのため、任意の位置にあるパターンを探す場合、明示的に変数を指定して、マッチしない文字を読み飛ばす必要があります。
パターンの例
;; aにマッチする
(cl-irregsexp:if-match-bind (_ "a") "abc")
(cl-irregsexp:if-match-bind (_ "a") "bca")
(cl-irregsexp:if-match-bind (_ "a") "cab")
(cl-irregsexp:if-match-bind (_ #\a) "abc")
(cl-irregsexp:if-match-bind (_ #\a) "bca")
(cl-irregsexp:if-match-bind (_ #\a) "cab")
;=> T
;; itにマッチする
(cl-irregsexp:if-match-bind (_ "it") "hit")
(cl-irregsexp:if-match-bind (_ "it") "its")
(cl-irregsexp:if-match-bind (_ #\i #\t) "hit")
(cl-irregsexp:if-match-bind (_ #\i #\t) "its")
;=> T
;; 任意の文字にマッチする
(cl-irregsexp:if-match-bind ((char)) "abc")
;=> T
;; マッチした任意の文字をanyに束縛する
(cl-irregsexp:if-match-bind ((any (char))) "abc" any)
;=> "a"
;; 任意の3文字にマッチする
(cl-irregsexp:if-match-bind ((char) (char) (char)) "abc")
;=> T
;; マッチした任意の3文字をそれぞれxとyとzに束縛する
(cl-irregsexp:if-match-bind ((x (char)) (y (char)) (z (char)))
"abc"
(concatenate 'string x y z))
;=> "abc"
;; アルファベットにマッチする
(cl-irregsexp:if-match-bind ((or (- #\a #\z) (- #\A #\Z))) "abc")
;=> T
;; マッチした1文字以上のアルファベットをwordに束縛する
(cl-irregsexp:if-match-bind ((word (+ (or (- #\a #\z) (- #\A #\Z))))) "abc" word)
;=> "abc"
;; aとbとcのいずれかにマッチする
(cl-irregsexp:if-match-bind ((or "a" "b" "c")) "abc")
(cl-irregsexp:if-match-bind ((or #\a #\b #\c)) "abc")
;=> T
(cl-irregsexp:if-match-bind ((or "a" "b" "c")) "def")
(cl-irregsexp:if-match-bind ((or #\a #\b #\c)) "def")
;=> NIL
;; aとbとc以外にマッチする
(cl-irregsexp:if-match-bind ((not (or "a" "b" "c"))) "abc")
(cl-irregsexp:if-match-bind ((not (or #\a #\b #\c))) "abc")
;=> NIL
(cl-irregsexp:if-match-bind ((not (or "a" "b" "c"))) "def")
(cl-irregsexp:if-match-bind ((not (or #\a #\b #\c))) "def")
;=> T
;; 行の最初のaにマッチする
(cl-irregsexp:if-match-bind ("a") "abc")
(cl-irregsexp:if-match-bind (#\a) "abc")
;=> T
(cl-irregsexp:if-match-bind ("a") "bca")
(cl-irregsexp:if-match-bind (#\a) "bca")
;=> NIL
;; 行の最後のcにマッチする
(cl-irregsexp:if-match-bind (_ "c" (last)) "abc")
(cl-irregsexp:if-match-bind (_ #\c (last)) "abc")
;=> T
(cl-irregsexp:if-match-bind (_ "c" (last)) "aaa")
(cl-irregsexp:if-match-bind (_ #\c (last)) "aaa")
;=> NIL
;; 整数にマッチする
(cl-irregsexp:if-match-bind ((i (integer))) "01234" i)
;=> 1234
(cl-irregsexp:if-match-bind ((i (integer))) "abcde" i)
;=> NIL
;; 浮動小数点数にマッチする
(cl-irregsexp:if-match-bind ((f (float))) "3.14" f)
;=> 157/50
(cl-irregsexp:if-match-bind ((f (float))) "a.bc" f)
;=> NIL
基本的なパターンマッチ
;; 戻り値はbody部分によって変わる
(cl-irregsexp:match-bind ((b (or (float) (integer))) (:? #\^ (e (integer))))
"3.14^10"
(values (read-from-string b) e))
;=> 3.14
; 10
;; マッチしない場合はエラー
(cl-irregsexp:match-bind ((a #\a)) "b" a)
;>> Error: #<CL-IRREGSEXP:MATCH-FAILED #x1918B48E>
条件式
パターンがマッチしたかどうかで処理を分岐します。
;; then部とelse部は省略でき、それぞれtとnilを返す
(cl-irregsexp:if-match-bind (#\a) "a")
;=> T
;; 応用例:十六進数を読み込む
(cl-irregsexp:if-match-bind ("0x" (hex (+ (or (- #\a #\f) (- #\0 #\9)))) (last))
"0xffff"
(values (read-from-string (format nil "#x~A" hex)))
(error "syntax error"))
;=> 65535
パターンの置換
;; 最初にマッチした部分を置換する
(cl-irregsexp:match-replace-one "<<<"
(#\< "<"))
;=> "<<<"
; 3
;; マッチする部分をすべて置換する
(cl-irregsexp:match-replace-all "<<<"
(#\< "<"))
;=> "<<<"
; 6
パターンによる分割
(cl-irregsexp:match-split #\: "a:b:c")
;=> ("a" "b" "c")