31

a*次の 0 個以上のインスタンスを意味します。

では、なぜ$_ = "a"; s/a*/e/g生成するのですか:ee

考えられる答え: 文字列 "a" を "e" に置き換え、空の文字列 "" を "e" に置き換えています。または、文字 a の単なる不在を文字 e に置き換えているか、「ゼロオカレンス」の a を an: e に置き換えています。

それでは、しかし:

$_ = "b"; s/a*/e/g生成:ebe

bの左側の空の文字列と、次の右側の空の文字列置き換えているようです:b

わかった。しかし、なぜそれが行われないのですか: " a" ? aget:の左側の空の文字列: a の右側の空の文字列、および文字: a 自体を置き換えないのはなぜeeeですか?

a のゼロオカレンスは、右側と同じくらい左側にあります!

4

5 に答える 5

19

Damian Conway の優れたRegexp::Debuggerを使用して、次のことを試しました。

perl -MRegexp::Debugger -E '$_ = "a"; s/a*/e/g; say'

そして、イベントログモードで示されている、物事をより明確にする場合に備えて、この出力を取得しました。置換を実行する最初のパスの一致により、次の一連のイベントが生成されます。

a               | a*              |   Starting regex match
a               | a*              |     Trying a literal character zero-or-more times (as many as possible)
                | a*              |     Matched
                |                 |   Regex matched in 3 steps

これは、「a」が最初に一致し、「e」に置き換えられることを示しています。

1 回目のマッチが完了した後、デバッガーは同じプログラムから 2 回目のマッチを実行させてくれます。

                | <~~             |   Back-tracking in regex
                | a*              |   Back-tracked and restarting regex match
                | a*              |     Trying a literal character zero-or-more times (as many as possible)
                | a*              |     Matched
                |                 |   Regex matched in 3 steps

これは、元の "a" (現在は "e") の後の "" が 2 回目に一致し、"e" に置き換えられたことを示しています。

残念ながら、出力の読み方がわからないか、この時点で Regexp::Debugger が混乱するかのどちらかですが、もう一度繰り返しますが、置換は行いません。

                | <~~             |   Back-tracking in regex
                | a*              |   Back-tracked and restarting regex match
                | a*              |     Trying a literal character zero-or-more times (as many as possible)
                | a*              |     Matched
                |                 |   Regex matched in 3 steps

いずれにせよ、Perl が 3 回目のマッチングを行い、なんらかの理由で今回は置き換えを行わないことにしたか、または Regexp::Debugger か、単に混乱しているだけかのどちらかです。

編集: perldoc perlreを確認して混乱を解決しました:

「より高いレベルのループは、反復間の追加の状態を保持します: 最後の一致が長さ 0 であったかどうか。ループを壊すために、長さ 0 の一致の後の次の一致は長さ 0 を持つことが禁止されています。この禁止はバックトラッキングと相互作用します(「バックトラッキング」を参照)、最適な一致の長さがゼロの場合は、2 番目に最適な一致が選択されます。"

于 2012-08-08T00:06:33.157 に答える
1

とても好奇心が強い。RHEL 5 で Perl 5.12.1 を使用すると、出力は次のようになります。

$ perl -e '$_ = "a"; s/a*/e/g; print "$_\n";'
ee
$

私が思いつく最良の推測 (理由) は、最初の が にa*一致し、最初のaが生成されe、次に , の後の空の文字列aが 2 番目の に一致することeです。いくつかのバリエーションを試してみましょう:

$ perl -e '$_ = "a"; s/^a*/e/g; print "$_\n";'
e
$ perl -e '$_ = "a"; s/a*$/e/g; print "$_\n";'
ee
$ perl -e '$_ = "a"; s/a+/e/g; print "$_\n";' 
e
$

これらのバリエーションの最初と 3 番目は、私が期待する答えを生成します。2番目はまだ私を困惑させます。

$ perl -e '$_ = "a\n"; s/a*/e/g; print "$_\n";'
ee
e
$

うーん...

于 2012-08-07T23:49:18.160 に答える