お楽しみプログラム

JavaScript

正規表現

文字列のパターン検索に使われる「正規表現」。といっても、統一した記法があるわけではなく、アプリケーションや、言語によって、書き方や仕様が異なっています。

しかし、最近はPerlでの正規表現に準じた書き方が標準になりつつあるので、おおまかには、Perlでの書き方を中心に考えていけばよいようです。


ちょっとしたテスト

文字列の単純な検索を行って違いを見ます。検索結果の文字列は「,」で区切って表示しています。

言語ソース結果
お題:空マッチ
文字列 "123456789" を 空パターン () で一括検索する。
Perl.5.12/()/g
,,,,,,,,,
javascript
IE8
"123456789".match(/()/g)
,,,,,,,,,
cextraecho 123456789|cextra "()" -xt, -hg1
,,,,,,,,
cextraecho 123456789|cextra "()" -xt, -hg1 -hl
,,,,,,,,,
cextraecho 123456789|cextra "()" -xt, -hg2
,,,,,,,,,
cextraecho 123456789|cextra "()" -xt, -hg3
,,,,,,,,,
cextraecho 123456789|cextra "()" -xt, -hg3 -hl
,,,,,,,,,
お題:選択肢と空マッチ
文字列 "123456789" を 選択肢の付いた空パターン (|\d) で一括検索する。
Perl.5.12/(|\d)/g
,1,,2,,3,,4,,5,,6,,7,,8,,9,
javascript
IE8
"123456789".match(/|\d/g)
,,,,,,,,,
cextraecho 123456789|cextra "|\d" -xt, -hg1
,,,,,,,,
cextraecho 123456789|cextra "|\d" -xt, -hg1 -hl
,,,,,,,,,
cextraecho 123456789|cextra "|\d" -xt, -hg2
,1,2,3,4,5,6,7,8,9
cextraecho 123456789|cextra "|\d" -xt, -hg3
,1,,2,,3,,4,,5,,6,,7,,8,,9
cextraecho 123456789|cextra "|\d" -xt, -hg3 -hl
,1,,2,,3,,4,,5,,6,,7,,8,,9,
お題:全マッチ
文字列 "123456789" を 全マッチ (.*) で一括検索する。
Perl.5.12/(.*)/g
123456789,
javascript
IE8
"123456789".match(/.*/g)
123456789,
cextraecho 123456789|cextra ".*" -xt, -hg1
123456789
cextraecho 123456789|cextra ".*" -xt, -hg1 -hl
123456789,
cextraecho 123456789|cextra ".*" -xt, -hg2
123456789
cextraecho 123456789|cextra ".*" -xt, -hg3
123456789
cextraecho 123456789|cextra ".*" -xt, -hg3 -hl
123456789,

ここでチェックしたのは、結果が0幅になる可能性のあるものです。

一括検索(グローバル検索)では、一般的には、次の手順で行っています。

  1. 検索位置を対象文字列先頭にする。
  2. 検索する。
  3. 一致したら、一致文字列の末尾を次の検索位置にする。手順2へ。
  4. 一致しなければ終了する。

問題になるのは、一致の結果が長さ0の文字列、つまり、0幅の場合です。このとき、次の検索開始位置は、現在の検索開始位置と同じになってしまいます。同じ位置から同じ検索をするのですから、何度繰り返しても同じことになり、結局、無限ループになってしまいます。

これを避けるために、0幅の後、特別な処理をして、なんとか、検索ポイントを進めるようにしています。このときの論理は、「正規表現」で規定されているわけではなく、それぞれの処理系で工夫しているようです。従って、この動作に頼った書き方は、あまり、芳しくありません。

cextra.exe では、この動作を実験するために、次の4種類のモードを搭載し、オプション指定で切り替えて試せるようにしてあります。(通常は使う必要がありませんが…)

-HG0特に考慮しない。
-HG10幅マッチの後は1文字分強制的に進める。
-HG2最初の1回を除き、検索開始位置での0幅マッチをしない。
-HG30幅マッチの直後は(検索開始位置は変わらないが)、検索開始位置での0幅マッチをしない。(デフォルト)

また、通常は行末での空マッチを行わないようにしていますが、これを許可するオプション(-HL)もあります。

結果から推測すると、javascript では、-HG1 -HL を指定した場合と同じように動作するようです。 また、perl は、-HG3 -HL を指定した場合と同じように動作するようです。

メニューへ戻る
アルゴ算法堂へ戻る