正規表現について勉強したことのメモ。 正規表現の確認にはrubularというサイトを使う。
文字自体を表す正規表現
.
は「任意の1文字」を表す\w
は「英単語を構成する文字(半角英数字とアンダースコア)」を表す\d
は「半角数字1文字」を表す\t
は「タブ文字」を表す\n
は「改行文字」を表す\s
は「空白文字(スペース、タブ文字、改行文字)」を表す
文字の条件を指定する正規表現
a|b
は「aまたはb」を表すabc|def
は「文字列abcまたは文字列def」を表す[abc]
は「aまたはbまたはcが1文字」を表す[0-9]
は「0から9が1文字」を表す[a-z]
は「aからzが1文字」(文字コードで範囲を判定している)[^a]
は「aを除く任意の1文字」を表す[^abc]
は「aとbとcを除く任意の1文字」を表す
文字の数量を指定する正規表現
これ単独ではなく、文字または文字を表す正規表現と組み合わせて使う。
{n}
は「直前の文字がn文字」を表す{n,m}
は「直前の文字がn文字以上かつm文字以下」を表す{n,}
は「直前の文字がn個以上」を表す{,n}
は「直前の文字がn個以下」を表す?
は「直前の文字が0個または1個」を表す+
は「直前の文字が1個以上」を表す*
は「直前の文字が0個以上」を表す*
と+
は条件にマッチする最長の文字列を返す。最短マッチが欲しい場合は、*?
や+?
とする
最後のはいわゆる貪欲なマッチ(greedy match)を防ぎ、怠惰なマッチ(lazy match)を行うための方法。例えば、我輩は猫である。名前はまだ無い。
という文章から一文目を抽出したい場合、^.+。
だと最長マッチの我輩は猫である。名前はまだ無い。
が抽出されてしまうので、代わりに^.+?。
を使う。
位置を表す正規表現
文字そのものではなく、文字の前後の位置を表す。
^
は「行頭」を表す$
は「行末」を表す\b
は単語の境界を表す(?=a)
は「aの直前の位置」を表す(肯定の先読み、Positive Lookahead)(?=abc)
は「abcという文字列の直前の位置」を表す(?=a|b|c)
は「aまたはbまたはcの直前の位置」を表す
(?!a)
は「aでない文字の直前の位置」を表す(否定の先読み、Negative Lookahead)(?<=a)
「aの直後の位置」を表す(肯定の後読み、Positive Lookbehind)(?<!a)
「aでない文字の直後の位置」を表す(否定の後読み、Negaive Lookbehind)
先読み/後読みはちょっと複雑で覚えづらいが、利用場面は多い。例えば、aaa,bbb,ccc,ddd
のようなcsv文字列から3列目の値だけを置換したい場合、カンマそのものはキャプチャしたくないので、(?<=,)(.*?)(?=,)
でカンマの間の文字をキャプチャし、\2
で参照すれば良い。
キャプチャ関連の正規表現
()
で挟んだ部分はグループ化、またはキャプチャされる(?:)
でキャプチャを防ぐ- キャプチャした文字列は正規表現内でも
\1
や\2
といった連番で参照できる(後方参照)
後方参照は例えば、HTMLソースの中から<p></p>
もしくは<span></span>
タグで囲われている文字列を抽出したい場合、<(p|span)>.*<\/p|\/span>
とすると、<p></span>
や<span></p>
のように間違ったタグで囲われたものまで抽出されてしまう。このような場合は<(p|span)>.*<\/\1>
とすることで、正しく抽出することができる。(<\/\1>の初めのバックスラッシュは、閉じタグのスラッシュをエスケープするためのもの)