2016-08-14 6 views
0

次の正規表現は、Notepad ++エディタで試してみると適切な結果が得られますが、以下のperlプログラムで試しても間違った結果が得られます。正解と説明をお願いします。preで始まりalで終わる単語に一致する正規表現

次のように私は私のパターンをテストするために使用されるファイルへのリンクは次のとおりです。

http://sainikhil.me/stackoverflow/dictionaryWords.txt

正規表現:(。*)^事前アル(\は、* S)$

のPerlプログラム:

use strict; 
use warnings; 

sub print_matches { 
    my $pattern = "^Pre(.*)al(\s*)\$"; 
    my $file = shift; 

    open my $fp, $file; 

    while(my $line = <$fp>) { 
     if($line =~ m/$pattern/) { 
      print $line; 
     } 
    } 
} 

print_matches @ARGV; 
+1

ドル記号をエスケープしないでください –

+0

本当ですか?私はそれを行う場合、私は次のエラーを取得します。 最後の$は、ex2.pl 8行目の文字列 のex2.pl 8行目の "="^Pre(。*)al(\ s *)$ ""に近い構文エラーです。 – saint1729

+1

実際には、このOPのOPが正解です。 '$'は正規表現パターンではなく二重引用符で囲まれた文字列の中にあるため、エスケープする必要があります。 ''^Pre(。*)al(\ s *)\ $ "'(エスケープする必要があります)と '/^Pre(。*)al(\ s *)$ /'(エスケープしないでください。ちなみに、変数にパターンを普通の文字列として代入したい場合は、二重引用符の代わりに一重引用符を使用する場合は、 '$'をエスケープする必要はありません。 –

答えて

1

あなたが正規表現としてそれを使用する前に、変数にパターンを割り当て、あなたがそうするとき、二重引用符で囲まれた文字列でそれを置くことによって台無しになっています。

$をエスケープする必要があるのは、二重引用符で囲まれた文字列で、裸の$が変数の値を補間するためです。

$ perl -E 'say "^Pre(.*)al(\s*)\$";' 
^Pre(.*)al(s*)$ 

をその結果、ときに:あなたは単なるsを与える - \sにバックスラッシュがsをエスケープとして扱われるので、これはあなたの問題を引き起こしている(例えば、my $str = "foo$bar";

理由があります正規表現を実行しようとすると、0個以上の空白文字ではなく、0個以上の文字を探しています。sこのため

最も直接的な修正はバックスラッシュをエスケープするために、次のようになります。

$ perl -E 'say "^Pre(.*)al(\\s*)\$";' 
^Pre(.*)al(\s*)$ 

より良い修正は単一引用符の代わりに二重引用符を使用することであろうと$をエスケープしないでください:

$ perl -E "say '^Pre(.*)al(\s*)$';" 
^Pre(.*)al(\s*)$ 

一重引用符または二重引用符の代わりにqr(引用正規表現)演算子を使用することですが、後でそれを印刷して正規表現の内容を検証すると人間が判読できなくなりますなぜyであるかou're)最初の場所で変数に入れる:

$ perl -E "say qr/^Pre(.*)al(\s*)$/;" 
(?^u:^Pre(.*)al(\s*)$) 

あるいは、もちろん、ちょうどすべての変数に入れていないと

if($line =~ m/^Pre(.*)al(\s*)$/) ... 
+0

こんにちはデイブ、知識を共有してくれてありがとう。あなたの説明を見て、私は最近私のプログラムを編集しました。それはマッチングの代わりに私にすべての線を示しています。理由は何ですか? – saint1729

+0

@ saint1729 - 私の最後の2つの修正があなたを混乱させるようです。パターンを変数に代入している場合は、 'm $ $ $ $ $ $ \ $ \ $ \ $ \ $ \ 'ではなく' $ $ \ 'm /.../'では、 '$ _'の内容とマッチして一致しないようにしようとしていて、' $ pattern'に 'undef'を割り当てます。 'm /.../'を 'qr /.../ 'に変更すると、正しい結果が得られます(Prebendal、Predial、Prejudicial、Preternational、唯一の一致として)。 –

2

いくつかの考え:

  • あなたは空白の周りのキャプチャグループは.につながる

ドットの周りのキャプチャグループのために同じ

  • 無用であるドル記号
  • をエスケープするべきではありません。場合

    ^Pre.*al\s*$ 
    

    あなたはprecious finalのような言葉が(中間の空白のために、正規表現を:

    ^Pre\S*al\s*$ 
    

    はあなたのコードに含まれるもの:

    while(my $line = <$fp>) { 
         if($line =~ /^Pre\S*al\s*$/m) { 
          print $line; 
         } 
        } 
    
  • 1

    てみて、あなたのマッチングを行います末尾の改行文字(複数可)を除去:

    while(my $line = <$fp>) { 
         $line =~ s/[\r\n]+$//s; 
    

    をそして、alPreと終わりで始まるだけ言葉に一致するように、これを試してください

    :正規表現:あなたは両方 Prepre、大文字と小文字を区別しないマッチングを行う一致させたい場合は

    /^Pre\w*al$/ 
    

    \wは、単語の任意の文字だけでなく、任意の文字を意味する)と

    /^Pre\w*al$/i 
    
    関連する問題