正規表現では、"あ" という文字を指定すると、「あ」という文字そのもの にマッチする。"AB"という文字列を指定すると、「AB」という文字列そのものに マッチする。「AB」が行の途中にあっても構わない。 アルファベットや日本語など普通の文字や文字列を指定すると、 それ自身とマッチする。
通常の文字以外に、特別な記号を使うことで、文字そのもの以外に マッチする表現とすることができる。特別な意味を持つ記号について 解説する。検索のときに特別な意味を持つ文字のことを メタキャラクタ という。
Rubyで扱えるメタキャラクタのうち、代表的なものを示す。
.
(ピリオド)
記号 .
は、任意の1文字にマッチする。
たとえば、正規表現 ai.awa
は、"ai" のうしろに
何でもよいので何か1文字が来て、そのあとに "awa"
が続くようなもの全てにマッチする。たとえば、以下のようになる。
正規表現 | 照合する文字列 | マッチするか? |
---|---|---|
/ai.awa/ |
aikawa | ○ |
aizawa san | ○ | |
maisawa | ○ | |
aimoto | × | |
ai awa | ○ |
照合する文字列のうち実際にマッチしている部分には 下線が施してある(以下の例も同様)。
ピリオド自身を探したいときは\.
とする。
バックスラッシュには特殊文字の働きを打ち消す意味がある。以後の
[ ] ? * + ^ $ | ( )
についても同様で、それら自身を探
したいときにはそれぞれ、\[ \] \? \* \+ \^ \$ \| \( \)
というパターンを指定する。バックスラッシュ自身は\\
で探
す。
[ ]
(大括弧)
大括弧 [ ] は、その中に列挙した文字のどれか1文字
にマッチする。たとえば、正規表現 [abc]
は、
文字 a, b, c のどれかにマッチする。さらに、正規表現
ai[sz]awa
でいくつかの文字列と照合を行なったときの
結果は次のようになる。
正規表現 | 照合する文字列 | マッチするか? |
---|---|---|
/ai[sz]awa/ | aikawa | × |
aizawa san | ○ | |
maisawa | ○ | |
aimoto | × | |
ai awa | × |
大括弧の中で -
(ハイフン) を使うと文字の範囲を指定
できる。たとえば正規表現 [0-9]
は、文字 0 から文字
9 の範囲の全ての文字、つまり 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 のいず
れにもマッチする。もし、マッチする文字としてハイフン自体を指定した
いときは大括弧の先頭に記述する。たとえば、正規表現
[-a-z0-9]
は、「ハイフン、または aからz のどれか、また
は0から9のどれか1文字」にマッチする。
大括弧の中の先頭に ^
(山記号; キャレット) を指定す
ると、そのあとに列挙した文字以外 であるものにマッチする。
たとえば、正規表現 [^a-z]
は、aからz 以外の文字であれば
どれでもマッチする。
?
記号 ?
は、直前のパターンが0回か1回出現する
という意味を付加する。直前のパターンは文字でも記号でもよい。たとえ
ば、正規表現 sai?toh
は、?
の直前が
i なので、iが0個でも1個でもよいことを意味する。さらにたとえば、
正規表現 sa[ei]?ki
は、直前のパターンが
[ei]
なので、「eかi」の文字が0個でも1個でもよいことを
意味する。つまり、sa[ei]?ki
にマッチするのは、
saeki, saiki, saki
のどれかに限ることになる。
直前のパターンが0文字の場合にもマッチするので、
?
を正規表現の最後に付けたパターンで検索した
結果は付けないものと同じ結果となる。
例: sai?
は sa
で検索するのと同じ
結果になる(saの次にiがあった場合にマッチする範囲のみが異なる)。
*
記号 *
は、直前のパターンが0回以上出現する
という意味を付加する。直前のパターンは文字でも記号でもよい。たとえ
ば、正規表現 sai*toh
は、*
の直前が
i なので、iが0個以上なら何個でもよいことを意味する。つまり、
satohでもsaitohでもsaiitohでもsaiiiiiitohでもマッチする。
さらにたとえば、
正規表現 sa[ei]*ki
は、直前のパターンが
[ei]
なので、「eかi」の文字が0個以上なら何個でもよいことを
意味する。
正規表現 .*
は、直前のパターンが .
(任意の文字)なので、何でもよい文字列が何文字続いてもよいことを意味す
る。つまり、どんな文字列でもマッチする(よく使う)。典型的には
東北.*大学
のように2つのパターンの間に .*
を挟み、「『東北』と『大学』の間はなんでもいいや、なくてもいいや」
という検索をしたいときに使う。
直前のパターンが0文字の場合にもマッチするので、
*
を正規表現の最後に付けたパターンで検索した
結果は付けないものと同じ結果となる。
例: sai*
は sa
で検索するのと同じ
結果になる(saの次にiがあった場合にマッチする範囲のみが異なる)。
+
記号 +
は、直前のパターンが1回以上出現する
という意味を付加する。回数が「1回以上」という点を除いて記号
*
と全く同じと考えてよい。
直前のパターンが1文字の場合にもマッチするので、
+
が正規表現の最後になることはない
(+
を最後に書くのなら、+
を
省略しても同じ行がマッチする)。
^
記号 ^
を正規表現の先頭に指定した
場合のみ、文字列の先頭にマッチする。たとえば、
正規表現 ^sato
は、先頭が sato から始まるもののみに
マッチする。文字列の途中に sato が含まれてもマッチしない。つまり、
以下のようになる。
正規表現 | 照合する文字列 | マッチするか? |
---|---|---|
/^sato/ | sato san | ○ |
satoh desu | ○ | |
I am sato | × | |
Sato! | × |
$
記号 $
を正規表現の
末尾に指定した場合のみ、
文字列の末尾にマッチする。たとえば、
正規表現 sato$
は、sato で終わる文字列のみに
マッチする。
|
記号 |
(縦棒; パイプ) は、「または」の意味で、
|
の左右のパターンどちらかにマッチすればよいことを意
味する。たとえば、正規表現 SAITO|IIMORI
は、
SAITO または IIMORI のどちらかにマッチする。
( )
丸括弧 ( )
は、長い正規表現の一部分だけを括るとき
に利用する。たとえば、正規表現
a(wa|ma|yanokou)ji
は、|
で
選択する単語の範囲を限定しているので、結果として awaji, amaji, ayanokouji
のどれかを含むものにのみマッチする。
また、正規表現 a(re)+
は、+
の
直前のパターンを括弧で括り (re)
としているので、
are, arere, arerere, arererere, ... などにマッチする。もし
( )
で括らずに、are+
とすると、
+
の直前が e だけになるので、are, aree, areee, ...
にマッチすることになる。
このように、正規表現の一部を丸括弧で括って一つのかたまりにする ことを、グルーピングという。元の文字列のうち、グルーピン グした部分にマッチした部分文字列はあとで抽出することができる。
\数字
バックスラッシュ \
の後ろに数字 N を続けると、元の
正規表現のN番目の括弧にマッチした文字列そのものに置き換えられる。
たとえば、正規表現 (bye|ciao) \1
は、最初の括弧で
"bye" または "ciao" にマッチする。次の \1
は、1番目の
括弧でマッチした文字列そのものに置き換えられるので、最初にマッチし
たものが "bye" なら "bye" 、"ciao"なら"ciao"にマッチする。つまり、
"bye bye" または "ciao ciao" のみにマッチする。もし、
\1
を使わずに、正規表現を (bye|ciao) (bye|ciao)
とすると、2個目の括弧も "bye" "ciao" どちらでもよくなるの
で、"bye bye", "bye ciao", "ciao bye", "ciao ciao" どれにでもマッ
チすることになる。\数字
を使うと、1行の中にある文字列
が繰り返して現れるパターンを記述することができる。
\b
正規表現中の \b
は、「単語の境界」にマッチする。
たとえば、正規表現 station
で検索すると
"stationery" や "attestation" がマッチするが、正規表現
\bstation\b
は、"s" の前と "n" の後ろが単語の境目になっ
ているものにしかマッチしないため、"…… station ……" のように
単語として独立した "station" を含むものにしかマッチしない。
\s
正規表現中の \s
は、あらゆる空白
文字にマッチする。スペースやTAB文字、改行文字などにマッチす
る。
\S
正規表現中の \S
は
空白文字以外の全ての文字にマッチする。
ちょうど\s
の逆である。
\d
正規表現中の \d
は、0から9(半角)のどれかにマッチする。
たとえば、正規表現 \d+
は、0から9が1回以上くり返したも
のにマッチするので、数字と思われるもの全てにマッチする。
\D
\D
は、数字以外の全ての文字にマッチする。
\d
の逆である。
\w
\w
は、単語を構成する文字の
どれか、つまり英数字 [0-9A-Za-z_]
や日本語文字のどれかにマッチする。ただし、
日本語文字にマッチするのは次節の正規表現オプションで
日本語検索を有効にした場合に限る。
\W
\W
は、\w
の逆で単語構成文字以外の1字にマッチする。
/ /
で括った正規表現の直後に文字を追加すると
正規表現の検索方法を変えることができる。
たとえば、デフォルトでは英字の大文字と小文字を区別した検索を行なうが、
正規表現指定の直後にiを付けて、
/abcde/i
とすると、大文字と小文字を区別せずに
検索するようになる。これを正規表現オプションという。
このようなオプションのうち覚えておくべきものを紹介する。
i
- 大文字小文字を区別しない
m
- 文字列中に改行が含まれていても
.
でマッチするようになる
最初に紹介したRubyでの正規表現指定方法は、パターンを / / で括るという ものだった。それ以外にもいくつか方法がある。 プログラム中で正規表現を指定するには以下のどれかを使う。
/パターン/
もっとも簡単な指定方法。既に利用した。
%r,パターン,
%r
の直後の文字でパターンを挟む。上記の例では
,
(カンマ) だが、括弧で括ったり、括弧以外の任意の文字
で挟むことができる。%r(パターン)
でも
%r|パターン|
でも%r!パターン!
でもよい。ただし、挟むための右側の文字がパターン中に現れてはいけない。
本講では使わないが、すこし複雑な正規表現を指定するときには
どうしても必要。たとえば、/
をたくさん含む文字列を
検索したいときはパターンの区切り文字に /
以外を利用で
きるこの表記が便利で、日付けらしき文字列を探すときに
%r:\d\d\d\d/\d\d?/\d\d?:
などとすると「4桁の数値/1、2桁の数値/1、2桁の数値」にマッチする
パターンが書ける。%r
を使わず / /
で括ると、
/\d\d\d\d\/\d\d?\/\d\d?/
となり、スラッシュの境目が分かりづらい。
Regexp.new(パターン文字列)
文字列を正規表現に変換する。プログラム中で
pattern = "sai?toh"
/sai?toh/
に変換したいときは、
regexp = Regexp.new(pattern)
とする。本講で使う。プログラム作成時ではなく、起動したときに
検索パターンを読み込みそれ正規表現に変換するのであれば、
Regexp.new
が必要。
大文字小文字を区別して欲しくない場合は、第2引数に
true
を指定する。
regexp = Regexp.new(pattern, true)
とすると /sai?toh/i
と同じことになる。
true
の代わりに
Regexp::IGNORECASE
(大文字小文字を区別しない)
Regexp::MULTILINE
(.
が改行にマッチする)
Regexp::EXTENDED
(拡張)
を指定することもできるが本講では扱わない。