14

照合しようとしている行を含むファイルがあるとします。

foo
quux
bar

私のコードには、別の配列があります。

foo
baz
quux

$wordファイルを反復処理し、各要素と、チェック対象の内部リストを呼び出すとしましょう@arr

if( grep {$_ =~ m/^$word$/i} @arr)

fo.これは正しく機能しますが、ファイルにのテストケースがある可能性のあるケースでは.、は正規表現でワイルドカード演算子として動作し、fo.次に一致fooします。これは受け入れられません。

もちろん、これはPerlが変数を正規表現に補間しているためです。

質問:

Perlに変数を文字通り使用させるにはどうすればよいですか?

4

5 に答える 5

34

\Q...\E変数値の補間後に、perl 文字列で特殊記号を直接エスケープするために使用します。

if( grep {$_ =~ m/^\Q$word\E$/i} @arr)
于 2010-01-04T18:25:12.227 に答える
18

perlfaq6の回答から、変数内の正規表現にどのように一致させますか? :


一致演算子 (または正規表現で機能するその他のもの) にパターンをハードコーディングする必要はありません。後で使用するためにパターンを変数に入れることができます。

一致演算子は二重引用符のコンテキストであるため、二重引用符で囲まれた文字列と同じように変数を補間できます。この場合、正規表現をユーザー入力として読み取り、$regex に保存します。$regex でパターンを取得したら、その変数を一致演算子で使用します。

chomp( my $regex = <STDIN> );

if( $string =~ m/$regex/ ) { ... }

$regex 内の正規表現の特殊文字は依然として特殊であり、パターンが有効である必要があり、そうでない場合、Perl は文句を言います。たとえば、このパターンでは対になっていない括弧があります。

my $regex = "Unmatched ( paren";

"Two parens to bind them all" =~ m/$regex/;

Perl が正規表現をコンパイルするとき、括弧をメモリ一致の開始として扱います。閉じ括弧が見つからない場合、次のように文句を言います。

Unmatched ( in regex; marked by <-- HERE in m/Unmatched ( <-- HERE  paren/ at script line 3.

状況に応じて、いくつかの方法でこれを回避できます。まず、文字列内のどの文字も特別なものにしたくない場合は、文字列を使用する前に quotemeta でエスケープできます。

chomp( my $regex = <STDIN> );
$regex = quotemeta( $regex );

if( $string =~ m/$regex/ ) { ... }

\Q および \E シーケンスを使用して、一致演算子で直接これを行うこともできます。\Q は Perl に特殊文字のエスケープを開始する場所を伝え、 \E は停止する場所を伝えます (詳細については perlop を参照してください)。

chomp( my $regex = <STDIN> );

if( $string =~ m/\Q$regex\E/ ) { ... }

別の方法として、正規表現の引用演算子である qr// を使用することもできます (詳細については perlop を参照してください)。パターンを引用しておそらくコンパイルし、パターンに正規表現フラグを適用できます。

chomp( my $input = <STDIN> );

my $regex = qr/$input/is;

$string =~ m/$regex/  # same as m/$input/is;

全体を eval ブロッ​​クでラップして、エラーをトラップすることもできます。

chomp( my $input = <STDIN> );

eval {
    if( $string =~ m/\Q$input\E/ ) { ... }
    };
warn $@ if $@;

または...

my $regex = eval { qr/$input/is };
if( defined $regex ) {
    $string =~ m/$regex/;
    }
else {
    warn $@;
    }
于 2010-01-04T18:30:53.430 に答える
13

正解は、正規表現を使用しないことです。正規表現が悪いと言っているわけではありませんが、単純な等値チェック (に相当するもの) に正規表現を使用するのはやり過ぎです。

使用:grep { lc($_) eq lc($word) } @arrそして幸せになる。

于 2010-01-04T18:30:03.077 に答える
5

Quotemeta

「単語」以外のすべての文字をバックスラッシュしたEXPRの値を返します。

http://perldoc.perl.org/functions/quotemeta.html

于 2010-01-04T18:21:35.230 に答える
2

この場合、パターンに一致していないため、正規表現は必要ないと思います。既に知っている文字のリテラル シーケンスを探しています。一致する値でハッシュを作成し、それを使用してフィルター処理します@arr

 open my $fh, '<', $filename or die "...";
 my %hash = map { chomp; lc($_), 1 } <$fh>;

 foreach my $item ( @arr ) 
      {
      next unless exists $hash{ lc($item) };
      print "I matched [$item]\n";
      }
于 2010-01-04T18:36:02.563 に答える