しょぼしょぼすくりぷと xyzzy > lisp programing > TIPS LIST > 正規表現でテストして遊ぶ

正規表現でテストして遊ぶ

--

必要レベル

  • 正規表現を使ったことがある。
  • メタキャラクタという物をいくつか知っている

xyzzy上の正規表現の文法

基本的な正規表現(grepやsedで使われている)は使えるようです。

.+*?()[]^$|や \nなどのエスケープ記号は対応しています。 POSIXのような :digit:などや、Perlの拡張正規表現である \d等の形式は対応していません。 また グルーピングは \(とエスケープが必要になります。

refer: xyzzyの正規表現の表記(wiki) | 正規表現(wikipedia)
ファイラーによる 正規表現活用例(rename)
リファレンス(wiki) > Type > Tips > Emacs 互換ではない正規表現は結構あるのでしょうか?

正規表現の種類

4パターンに分けて正規表現文字とその意味を説明します。

  1. 繰り返し
  2. 文字種系
  3. パターン系
  4. 位置系
なので、使い方は (位置) (文字種 or パターン)(繰り返し)の並び順になると思います。

(A).繰り返し

?01234567任意の1文字(あり(1文字) or なし(0文字))
+@0+
=>@0000123
=>@0123
=>NG:@123
存在文字数(1文字以上)
* @0*
=>@00000123
=>@123
直前の文字orグループがあってもなくても良い(0文字も含む)
@\{M,N\}    |-M文字-|
    |-----N文字-----|   
... ..@@@@...@@@@...
M回~N回(MまはたNのどちらかを省略した場合、その方向に無制限)
@\{L\}   |-L文字-|   
...@@@@@...
直前の文字orグループのL回のみ
繰り返しに?をつけると 最長マッチではなく、最短マッチとなります。
e.g. ??、*?、+?、\{\}?、\(?:\)など
Version 0.2.1.186

(B).文字種

文字のメタ情報を表す正規表現

.01234567任意の1文字
\w+01234567luckey##英数字の1文字
\W+01234567luckey##英数字以外の1文字
\++01234567正規表現文字そのもの1文字
\spoint-maxシンタックス文字
\sw \s \s( \s. など
\Spoint-max__"pop"シンタックス文字以外
\_spoint_maxシンボル文字
\_Spoint_max__"life"シンボル文字以外

ざっくり説明すると、
Javaのシンボル: 変数に使えるもの
Javaのシンタックス:ソースに書ける文字全部(空白とかは除くのかな)

だから言語によってsymbolの指すものは少し違う。詳しくはリファレンスや java.lなど参考に!

シンタックスコードはこちらが参考になります。 refrence:skip-syntax-spec-forward日記(Ultima Thule)

(C).パターン

[ ... ]文字のorマッチ,文字群の無名定義
(単語のorマッチの場合()を使う)
[123]+活01234567luckey##括弧内の文字パターン群
[0-9]+01234567luckey##括弧内の文字範囲パターン群
[^123]+1234567luckey##括弧内の文字以外パターン群
\( ... \)単語の定義(名前は グルーピング順序で\1 ,\2と後方参照可能)
\(?:regexp\)単語後方参照不可
\|\(090\) | \(080\) =>OK:09011
=>NG:122128
前後のどちらかがあればマッチ

(D).位置系

位置のメタ情報を表す正規表現

\`バッファ先頭
^ (<- 行頭)(行末 ->) $
\b [WORD]   \B 単語の境界
  \<\> 単語の開始・終了
\_b   \_B シンボルの境界
  \_<\_> シンボルの開始/終了位置
\'バッファ最後

正規表現を動かしてみる!!

キーワード指定に正規表現を使った例 , ファイラーのファイル置換に正規表現を使った例,

基礎

;基礎
a
'a' という1文字にマッチ

a.b
"ab" or "adb" or "a7b" .... 等 任意の文字
(string-match "a.b" "a8b")
0
(string-match "a.b" "a&b")
0

a?xyz
"xyz" "axyz" など 直前の文字が0か1文字の時
a+
"a" "aaaaaaaaa" など 1文字以上
ba*
"b" "ba" "baa" "baaaaaaaa" など0文字以上

[Xx]yzzy
"Xyzzy" or "xyzzy" []の中はそのうちどれか

[^x]yzzy
[^]の場合その要素以外(補集合)
(string-match "[^x]yzzy" "yzzy")
nil
(string-match "[^x]yzzy" "xyzzy")
nil
(string-match "[^x]yzzy" "ayzzy")
0

[0-9]abc
[]の中の - は 連続 この場合[0123456789]と同じ
[]の中では - [ ] ^ *など 場所によって働かない場合もあるので注意
(string-match "[0-9]abc" "7abc")
0
(string-match "[0-9]abc" "0abc")
0
(string-match "[0-9]abc" "Aabc")
nil

\
メタキャラクタそのものを指定したい場合直前に入れる(エスケープするという)
(string-match "\]a" "]a")
0
(string-match "\*a" "*a")
0

\t
特別な文字。この場合タブ文字(\nなど)
(string-match "\t" "	")
0

\{m\}
\{m,\}
\{,n\}
\{m,n\}
m回(m回以上、n回以下、m回からn回)繰り返し。
本当は上のように描くが エスケープされて "\{" が "{"になってしまうためかきのようにエスケープ記号をエスケープする。
また "\\{" "\{"になる。 "\\\{" は "\\" "\{"に分かれて "\{"と解釈される
このように文字列のエスケープと正規表現のごった煮のミスがよくある

(string-match "a\\{3\\}" "aa")
nil
(string-match "a\\{3\\}" "baaa")
1
(string-match "a{3}" "aaa")
nil
(string-match "a\\\{3\\\}" "aaa")
0
(string-match "ba\\{1,3\\}b" "baaaab")
nil
ちと休憩。、、、、、

正規表現の特殊記号

;位置など
^
先頭
$
最後
行レベルで考えますので、行頭や行の最後の位置を明示します。
(string-match "^abc" "abc")
0
(string-match "^abc" "kabc")
nil
(string-match "abc" "kabc")
1
(string-match "^abc$" "abc")
0
(string-match "^abc$" "abc;")
nil

\\<
\\>
単語の最初と最後にマッチ

(string-match "\\<abc\\>" "abc")
0
(string-match "\\<abc\\>" "jabc")
nil
(string-match "abc" "jabc")
1

\\(
\\)
グルーピング

\\1
グルーピングしてマッチした順番
後でさっき見た物を再利用できます。
(string-match "\\(abc\\)\\1" "Zabcabc")
1
(string-match "\\(abc\\)\\1" "abc")
nil
回文みたいなのとか
(string-match "\\(.\\)\\(.\\)\\(.\\)\\3\\2\\1" "abccba")
0
(string-match "\\(.\\)\\(.\\)\\(.\\)\\3\\2\\1" "abcabc")
nil

|(縦棒)
どちらか
(string-match "maru\\|batu" "maru")
0
(string-match "maru\\|batu" "batu")
0
ちと休憩。、、、、、 息継ぎおば

;特殊意味
\w
英数字
\W
英数字以外
_(under-bar)はだめみたい
\tと根本的に意味が違うことに注意
(string-match "a\\wc" "abc")
0
(string-match "a\\wc" "a0c")
0
(string-match "a\\wc" "a-c")
nil
(string-match "a\\Wc" "abc")
nil
(string-match "a\\Wc" "a0c")
nil
(string-match "a\\Wc" "a-c")
0

(string-match "\\sw" "abc")
0
(string-match "\\sw" "123")
0

(string-match "\\s " "    ")
0

(string-match "\\s " "abc")
nil

(string-match "\\sk" "カナ")
0

(string-match "\\sk" "かな")
nil


(string-match "\\_s+" "abc-abc")
0
(string-match "\\_s+" "0abcabc")
0
(string-match "\\_s+" "abc_abc")
0



(string-match "\\_S+" " ##")
0
(string-match "\\_S+" "abc")
nil


(string-match "\\w+" "abcabc")
0



正規表現活用サンプル

それでは少し現実的な正規表現の複合例を示します。


拡張子が zip かどうか
(string-match "\.zip$" "achive.zip")
6
(string-match "\.zip$" "achive.zip.scr")
nil

200?年にマッチ
(string-match "200[0-9]" "2001/2/2")
0

ある日付フォーマットにマッチ
(string-match "[0-9]\\{4\\}/[0-9]\\{,2\\}/[0-9]\\{,2\\}" "2001/2/2")
0
(string-match "[0-9]\\{4\\}/[0-9]\\{,2\\}/[0-9]\\{,2\\}" "1997/04/31")
0

タグの閉じ括弧に対応
正確にやるにはもっと大変。
(string-match "<[^>]+>.*\\(</[^>]+>\\)?" "<h1></h1>")
0

(string-match "プリンター\\|プリンタ" "私のプリンター")
2
(string-match "プリンター?" "どこののプリンタ")
4

;


正規表現についてはこんな感じです。

グルーピングの例として、 ファイラーのファイル置換に正規表現を使った例,

正規表現でlispを書くときに、知っておくと便利な Tips

meta文字の クォート

(regexp-quote "^head\\.left[0-9]*%")
"\\^head\\\\\\.left\\[0-9]\\*%"



しょぼしょぼすくりぷと xyzzy | lisp programing