これが、コードが機能しない理由の長い説明です。
修飾子は、正規表現の/g
動作を「グローバル マッチング」に変更します。これは、文字列内のすべてのパターンに一致します。ただし、このマッチングがどのように行われるかはcontextによって異なります。Perl の 2 つの (主な) コンテキストは、リスト コンテキスト(複数形) とスカラー コンテキスト(単数形) です。
list contextでは、グローバル正規表現一致は、一致したすべての部分文字列のリスト、または一致したすべてのキャプチャのフラット リストを返します。
my $_ = "foobaa";
my $regex = qr/[aeiou]/;
my @matches = /$regex/g; # match all vowels
say "@matches"; # "o o a a"
スカラーコンテキストでは、一致は正規表現が一致したかどうかを説明する perl ブール値を返すようです:
my $match = /$regex/g;
say $match; # "1" (on failure: the empty string)
ただし、正規表現はiteratorに変わりました。正規表現の一致が実行されるたびに、正規表現は文字列内の現在の位置から開始され、一致を試みます。一致する場合は true を返します。マッチングに失敗した場合、
- 一致は false を返し、
- 文字列内の現在の位置が開始に設定されます。
文字列内の位置がリセットされたため、次の一致は再び成功します。
my $match;
say $match while $match = /$regex/g;
say "The match returned false, or the while loop would have go on forever";
say "But we can match again" if /$regex/g;
2 番目の効果 - 位置のリセット - は、追加の/c
フラグでキャンセルできます。
pos
文字列内の位置は関数でアクセスできます:pos($string)
のように設定できる現在の位置を返しますpos($string) = 0
。
正規表現は、文字列の先頭に正規表現を固定するの\G
と同じように、現在の位置にアサーションを固定することもできます。^
このm//gc
スタイルのマッチングにより、トークナイザーを簡単に作成できます。
my @tokens;
my $_ = "1, abc, 2 ";
TOKEN: while(pos($_) < length($_)) {
/\G\s+/gc and next; # skip whitespace
# if one of the following matches fails, the next token is tried
if (/\G(\d+)/gc) { push @tokens, [NUM => $1]}
elsif (/\G,/gc ) { push @tokens, ['COMMA' ]}
elsif (/\G(\w+)/gc) { push @tokens, [STR => $1]}
else { last TOKEN } # break the loop only if nothing matched at this position.
}
say "[@$_]" for @tokens;
出力:
[NUM 1]
[COMMA]
[STR abc]
[COMMA]
[NUM 2]