9

この正規表現では

$line = 'this is a regular expression';
$line =~  s/^(\w+)\b(.*)\b(\w+)$/$3 $2 $1/;

print $line;

$2 が に等しいのはなぜ" is a regular "ですか? 私の思考プロセスは、 (.*) は貪欲で、行末まですべての文字に一致する必要があるため、$3 は空になるというものです。

しかし、それは起こっていません。正規表現マッチャーは、最後の単語境界の直前で何らかの形で停止し、最後の単語境界の後にあるものを $3 に入力し、残りの文字列は $2 に送信されます。

説明はありますか?ありがとう。

4

4 に答える 4

15

$3この正規表現を使用する場合、 を空にすることはできません。これは、対応するキャプチャ グループが(\w+)であるためです。これは、少なくとも 1 つの単語文字と一致する必要があります。そうしないと、一致全体が失敗します。

したがって、 (.*)" is a regular expression" に\b一致し、文字列の末尾に一致し、一致に(\w+)失敗します。次に、正規表現エンジンは(.*)一致する "に戻りis a regular "(一致にはスペースが含まれることに注意してください)、\bの前の単語境界に一致し、" "eに一致します。(\w+)expression

その後に変更(\w+)すると、文字列全体を消費する、(\w*)期待した結果になります。(.*)

于 2012-10-14T02:36:34.537 に答える
6

貪欲とは、絶対にすべてに一致するようになるという意味ではありません。それは、可能な限り多くのことをしても、正規表現が成功することを意味します。

これは+、グループ 3 で を使用するため、空にすることはできず、+手段1 以上として成功することを意味します。

3 を空にしたい場合は、 に変更(\w+)して(\w?)ください。現在、?は 0 または 1 を意味するため、空になる可能性があるため、貪欲.*はすべてを取ります。注: これは、Perl が行を処理する方法により、Perl でのみ機能するようです。

于 2012-10-14T02:38:05.360 に答える
1

正規表現が文字列全体と一致するためには^(\w+)\b、最初の単語全体が\1. 同様に、\b(\w+)$は最後の単語全体が である必要があります\3。したがって、どんなに欲張っ(.*)ても「 is a regular 」しかキャプチャできず、そうでなければパターンは一致しません。文字列の照合中のある時点で、おそらく「正規表現です」全体を使用しましたが、バックトラックして一致.*させる必要があることがわかりました。\w+

于 2012-10-14T03:20:49.000 に答える
0

.*正規表現をどのように記述したかは、貪欲であるか非貪欲であるかは問題ではありません。まだまだマッチします。

その理由は、 と\bの間.*で使用したためです\w+

use strict;
use warnings;

my $string = 'this is a regular expression';

sub test{
  my($match,$desc) = @_;
  print '# ', $desc, "\n" if $desc;
  print "test( qr'$match' );\n";
  if( my @elem = $string =~ $match ){
    print ' 'x4,'[\'', join("']['",@elem), "']\n\n"
  }else{
    print ' 'x4,"FAIL\n\n";
  }
}

test( qr'^ (\w+) \b (.*)  \b (\w+) $'x, 'original' );
test( qr'^ (\w+) \b (.*+) \b (\w+) $'x, 'extra-greedy' );
test( qr'^ (\w+) \b (.*?) \b (\w+) $'x, 'non-greedy' );
test( qr'^ (\w+) \b (.*)  \b (\w*) $'x, '\w* instead of \w+' );
test( qr'^ (\w+) \b (.*)     (\w+) $'x, 'no \b');
test( qr'^ (\w+) \b (.*?)    (\w+) $'x, 'no \b, non-greedy .*?' );
# original
test( qr'(?^x:^ (\w+) \b (.*)  \b (\w+) $)' );
    ['this'][' is a regular ']['expression']

# extra-greedy
test( qr'(?^x:^ (\w+) \b (.*+) \b (\w+) $)' );
    FAIL

# non-greedy
test( qr'(?^x:^ (\w+) \b (.*?) \b (\w+) $)' );
    ['this'][' is a regular ']['expression']

# \w* instead of \w+
test( qr'(?^x:^ (\w+) \b (.*)  \b (\w*) $)' );
    ['this'][' is a regular expression']['']

# no \b
test( qr'(?^x:^ (\w+) \b (.*)     (\w+) $)' );
    ['this'][' is a regular expressio']['n']

# no \b, non-greedy .*?
test( qr'(?^x:^ (\w+) \b (.*?)    (\w+) $)' );
    ['this'][' is a regular ']['expression']
于 2012-10-14T04:38:08.657 に答える