正規表現について その2
最近体調がすぐれません。風邪が治らないうちにノロにやられてしまいました。ご飯が食べられなくてつらいです。
まあ、それは置いておいて前回の続きです。
行単位で処理する
さて、次のメタキャラは「^」です。先ほども見ましたね。しかしながら今回は入る所が違います。
^abc
ブラケットに収まっていません。こうすると「行の先頭からabc」となります。要するに行頭を示す為のメタキャラです。行頭があれば当然のごとく行末もあります。
abc$
サンプルに芸がありませんがこれで行末がabcの場合にマッチします。
さて、次の例はよく見かける例です。
^$
はい、行頭と行末をくっつけてます。要するに空改行の行にマッチします。
続いて
^.*$
行頭と行末の間に任意の文字の連続…と書くと非常にややこしいのですが、どんな行にでもマッチしちゃう表現です。
単語の操作
或る単語を引っ掛けてって処理はままある訳ですが、正規表現では単語って概念がありません。だからと言って諦める訳にもいかないのですがw
幸いな事にIndesignでは単語の頭とお尻を検出できるメタキャラが利用可能です。
\<...(単語の先頭) \>...(単語の最後)
これを
\<\w+\>
と言う具合に使います。「\w」で[0-9a-zA-Z_]ですのでおおよその単語はマッチします。あとは必要に応じてアポストロフィーだのハイフンを追記すればいいと思います。
hogeもしくはfuga
さて、選択肢が一文字の場合はブラケット内に列記すれば選択できました。今度は単語自体を選択肢として使いたい場合です。
hoge|fuga
はい、出てきたのは「|」です。選択肢を「|」で挟んでゆくだけです。
例えば
hoge|hogehoge|fuga|fugafuga
などとなっている場合、hogeかhogehogeまたはfugaまたはfugafugaがマッチします。
まとめてお得?
しかしながら、上の様な検索の仕方は少数です。実務では一部が選択肢として与えられたものを抽出するという事が多いのですが、そう言った場合は次の様に
(青木|鈴木)\s+.+$
()でくくられた部分が出てきました。グルーピングってやつです。ご覧の通り算数で()内を先に計算するってお約束と大差ありません。くくられた部分は一つの単位として評価されます。
例では山田もしくは鈴木に続くスペースがあって更に文字が行末まで続くものを抽出します。ようは山田さんか鈴木さんを抽出するってことですね。
空白って?
\sが出たので一応解説を。空白といってもtabやline feed、caridge returnなどなど色々ございます。\sに含まれる空白キャラクタは
\n......LF \r......CR \t......Tab \f......FF ......(space)
という具合に5種類ほどある訳ですが、日本語における全角スペースは含まれないのでややこしいです。
\s = [\n\r\t\f ]
という事です。しかしながら、Indesignではemスペース、enスペース、全角スペース、1/3スペース…という具合に書きなぐるのも面倒なぐらい種類がある訳です。
[~m~>~(~3~4~%~|~S~s~<~/~.\s]
これでIndesignの空白がひっかかります。ちなみに~が付くメタキャラはIndesignオリジナルの実装ですね。
最長と最短
さて、ここで最長一致と最短一致の説明をしておきましょう。正規表現では基本的に最長一致が基本となります。
a+
で「aaaaaaaaaa」という文字列を検索すれば全体がマッチします。今までの解説ではこれは当然の動作です。
a+?
とすると頭の1文字分のaにだけマッチします。これが最短一致です。方法は数量子に?をくっつけるだけと単純です。
ここで注意しないといけないのは数量子にくっつくという事。通常では?は直前の一文字が0または1文字あるかの判断に使われます。?が「*+?」の数量子(quantifier)にくっつく場合のみ最短一致となります。
?に?がくっつくというカオスなREが出来ますが、あるか無いかって部分に最短一致を求めた所で意味はありませんので実際に使う事は無いでしょう。
コードで…
手っ取り早いので下の例を見てくださいな。
[1215]+
上の例は\に続く三桁の数値ですが、これは8進数で書かれたコードと見なされます。よって、LFもしくはCRの塊が引っかかります。Windowsの改行コードですね。
[\x61-\x7a]
同様に\に続くxと数字で16進数コードです。上記の例は[a-z]と等価です。
先読みと後読み
ちょっとした条件を付けて続く文字を検索することってあるのと思うんだけど、その条件自体はひっかけたくない場合ってのも多々ある訳です。そう言う場合に威力を発揮するのが以下のlookaheadとかlookbehind(後読み先読みの機能)なんです。
と偉そうにごちゃごちゃ書いてますが、例を見た方が早いと思われるので
否定後読み(?<!)
ひっかけたいモノに対して先行して記述します。
(?<!\d)\d\d
という具合なんですが、これは2桁以上の数字の頭2桁にマッチします。(?<\d)で数字以外の文字との境界を検出しています。
肯定後読み(?<)
肯定ってぐらいですから、以下の様にすると…
(?<\d)\d\d
3桁以上続く数字の2桁目と3桁目にマッチしちゃいます。
肯定先読み(?=)
\d\d(?=\d+)
どんどんいっちゃいます。上の様にすると3桁以上続く数字の1桁目と2桁目にマッチします。
否定先読み(?!)
(?<!\d)\d\d(?!\d+)
最後は先読みの否定です。上記の例では2桁の数字にのみマッチします。(3桁以上は(?!\d+)の部分ではじくわけです。
頭から評価してみましょう。(数字以外のキャラクタに続く)数字2桁(でそれ以降に数字が続かない)数字という具合ですね。
()の部分のは lookaheadもlookbehindもjust looking(みてるだけ〜)ということで条件を定義するもののマッチする部分には含まれない事にご注意下さい。
いやね、今回のエントリって、先読み後読みの?と!の順番ってどっちだっけ?って思ったのでメモ見返してまとめ上げたんだ。まあ、走らせてみれば一発な訳ですが、ここらで復習しておくのも良いかと思ったのが運の尽きでした。思ったよりもはるかに長かったw
結局延々とやりましたが、やりたかったのは一番最後のやつでしたw