逆引きxyzzy lisp(正規表現) - circleratio/xyzzy GitHub Wiki
(scan-buffer "[a-z]\\{3\\}" :regexp t)
=> nil
オプション指示をしなければ、現在のカーソル位置からバッファ末尾までを前方に検索する。
(string-match "a.c" "-abc")
=> 1
Common Lisp にはない関数.
(defun lookup (regexp)
(interactive "sRegxep: ")
(if (looking-at regexp)
(message "found")
(message "not found")))
(defun lookup-backward (regexp)
(interactive "sRegxep: ")
(save-excursion
(save-restriction
(narrow-to-region (point-min) (point))
(goto-char (point-min))
(if (scan-buffer (format nil "~A\\'" regexp)
:regexp t :case-fold nil)
(message "found")
(message "not found")))))
バッファの場合も文字列の場合も同じ。
(scan-buffer "[a-z]+" :regexp t)
=> t
(match-string 0)
=> "abc"
バッファの場合も文字列の場合も同じ。
(scan-buffer "[a-z]+" :regexp t)
=> t
(match-beginning 0)
=> 142
(match-end 0)
=> 147
scan-buffer で検索を行った時点の状態を保持できる. 復元を行った後には,match-string, match-beginning, match-end, replace-match を使える.
これにより,複数の検索結果を使った処理を楽に書ける.
(scan-buffer "[a-z]+" :regexp t)
=> t
(setq md (match-data))
=> #(38 39 nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)
(store-match-data md)
=> t
メタ文字の *, +, ? を使う。
"*" は直前の正規表現の 0 回以上の繰り返しにマッチする。
(string-match "a*c" "abc") => 2
(string-match "a*c" "ac") => 0
(string-match "a*c" "aaaaaac") => 0
(string-match "a*c" "c") => 0
(string-match "a*c" "abcccccc") => 2
(string-match "a*c" "abd") => nil
"+" は直前の正規表現の 1 回以上の繰り返しにマッチする。
(string-match "a+c" "abc") => nil
(string-match "a+c" "ac") => 0
(string-match "a+c" "aaaaaac") => 0
(string-match "a+c" "c") => nil
(string-match "a+c" "abcccccc") => nil
(string-match "a+c" "abd") => nil
"?" は直前の正規表現の 0回または 1 回の繰り返しにマッチする。
(string-match "a?c" "abc") => 2
(string-match "a?c" "ac") => 0
(string-match "a?c" "aaaaaac") => 5
(string-match "a?c" "c") => 0
(string-match "a?c" "abcccccc") => 2
(string-match "a?c" "abd") => nil
文字クラスを使う。
(string-match "[0-9]" "a") => nil
(string-match "[0-9]" "1") => 0
(string-match "[A-Z]" "M") => 0
(string-match "[A-Z]" "8") => nil
[]内で ^ を使うと、「それ以外」を表現できる。
(string-match "[^0-9]" "1") => nil
(string-match "[^A-Z]" "M") => nil
.は「改行文字を除く任意の1文字にマッチ」なので注意。 グルーピングを使うとよい。
(string-match "abc.*xyz" "abcdefg\nvwxyz") => nil
(string-match "abc\\(.\\|\n\\)*xyz" "abcdefg\nvwxyz") => 0
(match-string 0)
=> "abcdefg
vwxyz"
正規表現のグルーピングと match-string を使う。
match-string の引数は次のような意味を持つ。 :0: 正規表現に一致する文字列 :1-9:正規表現中のn番目のカッコに対応する文字列
(string-match "1\\(.\\)3\\(.\\)5\\(.\\)" "123456") => 0
(match-string 0) => "123456"
(match-string 1) => "2"
(match-string 2) => "4"
(match-string 3) => "6"
(string-match "\\([a-z]+\\),\\([0-9-]+\\),\\([^ ]+\\)" "tf,000-111-2222,Japan") => 0
(match-string 1) => "tf"
(match-string 2) => "000-111-2222"
(match-string 3) => "Japan"
(replace-buffer "[a-z]\\{3\\}" "OK" :regexp t)
=> 1
(scan-buffer "[a-z]+" :regexp t)
=> t
(replace-match "xyz")
=> t
(split-string "a,b,c/d" "[,/]")
=> ("a" "b" "c" "d")
(defun string-scan (regexp str)
(if (string-match regexp str)
(cons (subseq str (match-beginning 0) (match-end 0))
(string-scan regexp (subseq str (match-end 0) (length str))))
nil))
(string-scan "\\([^ ]+\\):\\([0-9-]+\\)" "inu:000-111-2222 saru:111-222-3333 gomi kiji:222-333-4444")
=> ("inu:000-111-2222" "saru:111-222-3333" "kiji:222-333-4444")
(defun process-pattern (str)
(interactive "sPattern: ")
(goto-char (point-min))
(while (scan-buffer str :regexp t)
(msgbox "~A:~A" (point) (match-string 0))
(forward-char)))
次の書き方ではうまく動作しない.
scan-buffer に no-dup を指示すると「ポイントの次の位置」を基点にするため,バッファ先頭にあるパターンにはマッチしないため.
(defun process-pattern (str)
(interactive "sPattern: ")
(goto-char (point-min))
(while (scan-buffer "aaa" :no-dup t :regexp t)
(msgbox "~A:~A" (point) (match-string 0))))
あまり効果はないので,よほどのことがない限り,使う必要なし.
(scan-buffer (compile-regexp "[a-z]+") :regexp t)
=> t
(regexp-quote "[abc](defg)*+")
=> "\\[abc](defg)\\*\\+"