web-dev-qa-db-ja.com

「AND NOT」操作の正規表現

私は、パターンxのすべてがパターンyに一致することを除いて、すべてに一致する一般的な正規表現構造を探しています。これを完全かつ簡潔に説明するのは難しい...正式な定義については Material Nonimplication を参照。

たとえば、任意のWord文字(\w)「p」を除く。注:大きいセット(すべてのWord文字)から小さいセット(文字「p」)を引いています。ただ言うことはできません[^p]これは、Word文字のみの大きな制限セットを考慮していないためです。この小さな例では、[a-oq-zA-OQ-Z0-9_]、これは苦痛ですが実行可能です。しかし、少なくとも大きな正のセットがより複雑な式になるように、より一般的な構造を探しています。いいねマッチ((?<=(so|me|^))big(com?pl{1,3}ex([pA]t{2}ern)「My」で始まる場合を除きます。

Edit:私はそれが悪い例だったことに気づきました。なぜなら、最初または最後にあるものを除外することは、ネガティブな先読みと後読みの表現が機能する状況だからです。 (ボヘミアン、私はまだこれを説明するために賛成票をくれました)。だから...真ん中のどこかに「My」を含む一致を除外するのはどうですか?...私はまだ次の擬似SQLに相当する正規表現のような一般的な構造を本当に探しています

select [captures] from [input]
where (
    input MATCHES [pattern1]
    AND NOT capture MATCHES [pattern2]
)

答えが「存在しないのにここに理由がある...」という場合は、それも知りたいです。

Edit 2:これを行うために独自の関数を定義したい場合は、次のようになります(C#LINQバージョンです):

public static Match[] RegexMNI(string input, 
                               string positivePattern, 
                               string negativePattern) {
    return (from Match m in Regex.Matches(input, positivePattern)
            where !Regex.IsMatch(m.Value, negativePattern)
            select m).ToArray();
}

私はまだこれを行うことができるネイティブの正規表現の構造があるかどうか疑問に思っています。

24
Joshua Honig

これは、is Wordでnotpである任意の文字に一致します。

((?=[^p])\w)

あなたの例を解決するには、入力のどこでも「My」にネガティブ先読みを使用します。つまり、(?!.*My)

^(?!.*My)((?<=(so|me|^))big(com?pl{1,3}ex([pA]t{2}ern)

入力の開始へのアンカーに注意してください^これを機能させるために必要です。

20
Bohemian

なぜ人々は大きなモノリシックな正規表現で複雑なことをしようとするのだろうか?

問題をサブパートに分割し、それらを個別に一致させるために本当に簡単な正規表現を作成できないのはなぜですか?この場合、最初に一致する\w、 その後一致 [^p]最初の一致が成功した場合。 Perl(および他の言語)を使用すると、1つの大きなblobby-regex(または、場合によっては短くて短い暗号正規表現)で必要なことを正確に実行できる、本当に複雑に見える正規表現を作成できます。 、しかし、だれかのために、あなたが行った後にコードを読む(そして維持する)必要があるのは、あなたはそれを完全に文書化する必要がある。最初から理解しやすいようにした方が良いでしょう。

申し訳ありませんが、大声で叫ぶ。

15
Kusalananda

編集後は、まだネガティブな先読みですが、追加の数量詞があります。

文字列全体に「My」が含まれていないことを確認したい場合は、これを行うことができます

(?!.*My)^.*$

ご覧ください ここRegexrで

これは、任意の文字シーケンスに一致します(.*の最後)と(?!.*My).*は、文字列のどこかに "My"があると失敗します。

正確に「My」ではないものに一致させたい場合は、アンカーを使用します

(?!^My$).*
5
stema

正規表現の先読み、後読み、ネスト、AND演算子、再帰、サブルーチン、条件、アンカー、およびグループについてこれらのトピックを調べた後、no solutionを満たすという結論に達しましたあなたが求めているもの。

先読みが機能しない理由は、この比較的単純なケースで失敗するためです。

Myを含まない3つの単語が1つとして含まれています。

正規表現:

^(?!。* My。*)(\ b\w +\b\s\b\w +\b\s\b\w +\b)

一致:

一つとして含まれています

最初の3つの単語は、Myが後に発生するため、一致しません。 「My」が文字列全体の最後にある場合、すべての先読みはすべて表示されるため失敗するため、何にも一致しません。

問題は、lookaheadには一致を開始する場所に関する暗黙的なアンカーがありますが、lookaheadがRegExの別の部分の結果に基づくアンカーで検索を終了する場所を終了する方法がないようです。つまり、目的のアンカーを手動で作成するには、すべてのRegExをネガティブ先読みに複製する必要があります。

これはイライラし、苦痛です。 「ソリューション」は、スクリプト言語を使用して2つの正規表現を実行しているようです。上下に重ねて。この種の機能が正規表現エンジンに組み込まれているのではないことに驚いています。

1
horta