読者です 読者をやめる 読者になる 読者になる

by shigemk2

当面は技術的なことしか書かない

S式から正規表現を作成する

Emacs Lisp

実行結果を見たら分かるように、Emacs正規表現は大量の\に汚染されて
とても見れたものじゃない。

というとで、rxというミニ言語マクロを利用してS式から正規表現文字列に変換する。

;; 文字列お指定すると文字列そのものにマッチする正規表現を作成する
(rx "foo")				; => "foo"
;; メタ文字はエスケープされる
(rx "foo+bar")				; => "foo\\+bar"
;; 複数の引数を指定した場合は、そのまま結合される
(rx "foo" "bar")			; => "foobar"
(rx ?a)					; => "a"
(rx not-newline)			; => "."
;; 全ての文字
(rx anything)				; => ".\\|\n"
(rx (any "a-z"))			; => "[a-z]"
(rx (in "a-z"))				; => "[a-z]"
;; [:space:]は空白文字
(rx (in "a" "be" space))		; => "[abe[:space:]]"
(rx (not (any "ab")))			; => "[^ab]"
(rx bol "a" eol)			; => "^a$"
;; \`は文字列先頭
(rx bos "foo")				; => "\\`foo"
;; \'は文字列末尾
(rx bos "exact" bos)			; => "\\`exact\\`"
(rx (group "foo"))			; => "\\(foo\\)"
;; \(?:〜\)は後方参照なしのグルーピング
;; 必要に応じてregexp-optが使われる
(rx (or "prog1" "progn"))		; => "prog[1n]"
;; group + orが使えるのがメリット
(rx (group (or "prog1" "progn")))	; => "\\(prog[1n]\\)"
;; |はorの別名
(rx (| "prog1" "progn"))		; => "prog[1n]"
(rx (? "any"))				; => "\\(?:any\\)?"
(rx (* "any"))				; => "\\(?:any\\)*"
(rx (+ "any"))				; => "\\(?:any\\)+"
(rx (*? "any"))				; => "\\(?:any\\)*?"
(rx (+? "any"))				; => "\\(?:any\\)+?"
(rx (?? "any"))				; => "\\(?:any\\)??"
;; 3回繰り返し
(rx (= 3 "three"))			; => "\\(?:three\\)\\{3\\}"
;; 3回以上
(rx (>= 3 "three"))			; => "\\(?:three\\)\\{3,\\}"
;; 3-4回
(rx (** 3 4 "three"))			; => "\\(?:three\\)\\{3,4\\}"
;; 後方参照
(rx (group "hoge") (backref 1))		; => "\\(hoge\\)\\1"
;; evalでフォームの評価結果
(rx (eval emacs-version))		; => "23\\.4\\.1"
;; 正規表現とrxの組み合わせ
(rx (or "literal" (regexp "re..xp")))	; => "literal\\|re..xp"

P176

Emacs Lispテクニックバイブル

Emacs Lispテクニックバイブル