1

文字列で探したいパターンのリストがあります。これらのパターンは多数あり、文字どおり一致させたい多数のメタ文字が含まれています。したがって、これは でのメタクォートに最適なアプリケーションです\Q..\E。複雑なのは、パターンの変数リストを正規表現に結合する必要があることです。

use strict;
use warnings;
# sample string to represent my problem
    my $string = "{{a|!}} Abra\n{{b|!!}} {{b}} Hocus {{s|?}} Kedabra\n{{b|+?}} {{b|??}} Pocus\n {{s|?}}Alakazam\n";

# sample patterns to look for    
my @patterns = qw({{a|!}} {{s|?}} {{s|+?}} {{b|?}});
# since these patterns can be anything, I join the resulting array into a variable-length regex
my $regex = join("|",@patterns);

my @matched = $string =~ /$regex(\s\w+\s)/; # Error in matching regex due to unquoted metacharacters
print join("", @matched); # intended result: Hocus\n Pocus\n

結合操作にメタクォートを導入しようとすると、効果がないように見えます。

# quote all patterns so that they match literally, but make sure the alternating metacharacter works as intended
my $qmregex = "\Q".join("\E|\Q", @patterns)."\E";

my @matched = $string =~ /$qmregex(\s\w+\s)/; # The same error

何らかの理由で、正規表現として使用する文字列にメタクォートが含まれている場合、メタクォートは効果がありません。私にとっては、正規表現に直接追加された場合にのみ機能しますが/\Q$anexpression\E/、私が知る限り、これはオプションではありません。どうすればこれを回避できますか?

4

1 に答える 1

1

パターンのいずれかが先行する唯一の文字列であるAbraため、期待される結果がわかりません。Kedabra

問題を解決するには、正規表現の各コンポーネントを as として個別にエスケープし、それらが表示される文字列の値のみに影響\Qを与える必要があります。あなたは書くことができます\E"\Q""\E""""\E|\Q""|"

my $qmregex = join '|', map "\Q$_\E", @patterns;

quotemetaしかし、関数を呼び出す方が簡単です。

また、リストを括弧で囲んで(?:...)代替を分離し、/g修飾子を正規表現一致に適用して、文字列内のすべての出現を検索する必要があります。

試す

use strict;
use warnings;

my $string = "{{a|!}} Abra\n{{b|!!}} {{b}} Hocus {{s|?}} Kedabra\n{{b|+?}} {{b|??}} Pocus\n {{s|?}}Alakazam\n";

my @patterns = qw(  {{a|!}} {{s|?}} {{s|+?}} {{b|?}}  );

my $regex = join '|', map quotemeta, @patterns;
my @matched = $string =~ /(?:$regex)(\s\w+\s)/g;
print @matched;

出力

 Abra
 Kedabra
于 2012-04-08T22:33:55.607 に答える