3

私は分離しなければならない

D= d1| d2|...|dn

F=f1|f2|...|fn

現時点では、次のようなifステートメントでこれら2つの正規表現をチェックしています。

if (($text_to_search =~ $D) && ($text_to_search !~ $F))

F を否定するにはどうすればよいですか? 選言全体または F のすべての選言に対して否定的なルックアラウンドを使用することは可能ですか?

私はこのように見えるはずです:

regexp = (d1)| (d2) | (d3)  ... (dn) | NOT (f1) | NOT (f2) | ... | Not (fn)

最初の単一の文字だけでなく、パターンを否定するために括弧が必要ですよね?

編集: たとえば、D は:a|b|c|dで、F は:1|2|3

動作は次のようになります。

input: "abc" --> accepted
input: "a" --> accepted
input: "abc1" --> Not accepted
input: "2" --> NOT accepted
input: "a2bc1" --> Not accepted
(input: "xyz999" --> does not match - shouldn't be accepted)

F-disjunct は、「入力シーケンスでこれを見たときに一致しない」のようにする必要があります

4

1 に答える 1

2

はい、否定先読みを使用できます。あなたの表記法を使用して、そのような結合された正規表現の形状を構築できます。

/(?!F)D/

ニュアンスはありますが。簡単な例を考えてみましょう。

my $patternD = '^(\d\d\d\d | \w\w)$';
my $patternF = 'AA | 12';

ご覧のとおり、patternD は 4 桁または 2 語の文字で構成される文字列に一致します。PatternF は または のいずれAAかに一致します12。したがって、次のフラグメントは、期待どおりに出力されます。

my $str = '1121';
print "patternD matches\n" if $str =~ /$patternD/x; # patternD matches
print "patternF matches\n" if $str =~ /$patternF/x; # patternF matches

それでは、単純なアプローチを使用して結合された正規表現を作成しましょう。

my $combined = "(?!($patternF))$patternD";
print "Combined regex matches\n" if $str =~ /$combined/x; # Combined regex matches?!

おっと、ここに偽陽性があります! (覚えておいてください、結合された正規表現は、正規表現 D が一致し、F が一致しない場合にのみ一致するはずですが、そうではありません)。どうしてこれなの?答えは簡単です。D がある位置で一致する場合、F は同じ位置からのみ一致できるように、組み合わせた正規表現を作成しました。この場合、D は$str(\d\d\d\d代替) の先頭で一致し、どちらAA12一致できません。ただし、解決策は簡単です。.*F の前に追加することで、F にある程度の柔軟性を持たせる必要があります。最終結果は次のとおりです。

 my $combined = "(?!.*($patternF))$patternD";

D がどこに一致しても、F は文字列のどこにでも一致する可能性があります。

この例は、達成したいことが間違いなく実行可能であることを示していますが、単純に 2 つの正規表現を混ぜ合わせることはできません。最初に最終結果を注意深く調べる必要があります。

HTH

于 2012-02-02T14:49:38.163 に答える