30

一部の正規表現フレーバーでは、[負の] ゼロ幅アサーション (先読み/後読み) がサポートされていません。

これにより、除外を述べることが非常に困難 (不可能?) になります。たとえば、「「foo」を含まないすべての行」は次のようになります。

^((?!foo).)*$

ルックアラウンドをまったく使用せずに同じことを達成できますか (複雑さとパフォーマンスの問題は今のところ脇に置いておきます)。

4

4 に答える 4

30

更新:@Cianticがコメントで指摘したように、「ooの前に2つのffで」失敗します。


^(f(o[^o]|[^o])|[^f])*$

注:上記の正規表現を使用する代わりに、クライアント側で一致を否定する方がはるかに簡単です。

正規表現は、そうでない場合は各行が改行文字で終わると想定しています。C++ と grep の正規表現を参照してください。

Perl、Python、C++ などのサンプル プログラムでは、grepすべて同じ出力が得られます。

  • パール

    #!/usr/bin/perl -wn
    print if /^(f(o[^o]|[^o])|[^f])*$/;
    
  • パイソン

    #!/usr/bin/env python
    import fileinput, re, sys
    from itertools import ifilter
    
    re_not_foo = re.compile(r"^(f(o[^o]|[^o])|[^f])*$")
    for line in ifilter(re_not_foo.match, fileinput.input()):
        sys.stdout.write(line)
    
  • c++

    #include <iostream>
    #include <string>
    #include <boost/regex.hpp>
    
    int main()
    {
      boost::regex re("^(f(o([^o]|$)|([^o]|$))|[^f])*$");
      //NOTE: "|$"s are there due to `getline()` strips newline char
    
      std::string line;
      while (std::getline(std::cin, line)) 
        if (boost::regex_match(line, re))
          std::cout << line << std::endl;
    }
    
  • grep

    $ grep "^\(f\(o\([^o]\|$\)\|\([^o]\|$\)\)\|[^f]\)*$" in.txt
    

サンプルファイル:

foo
'foo'
abdfoode
abdfode
abdfde
abcde
f

fo
foo
fooo
ofooa
ofo
ofoo

出力:

abdfode
abdfde
abcde
f

fo
ofo
于 2009-01-21T17:16:53.597 に答える
2

正規表現内のシーケンスを除外しようとしている、独自の正規表現除外ソリューションを探しているこの質問に出くわしました。

この状況に対する私の最初の反応: たとえば、「「foo」が含まれていないすべての行」 は、grep で一致するオプションの -v invert を単純に使用することでした。

grep -v foo

これは、「foo」に一致しないファイル内のすべての行を返します

単純すぎて質問を読み違えてしまった感が強い…。

于 2009-08-06T17:05:46.087 に答える
1

通常、foo を探して、正規表現一致の結果をクライアント コードから反転させることができます。

簡単な例として、文字列に特定の文字のみが含まれていることを検証したいとします。

次のように記述できます。

^[A-Za-z0-9.$-]*$

true結果を有効なものとして受け入れるか、次のようにします。

[^A-Za-z0-9.$-]

false結果を有効なものとして受け入れます。

もちろん、これは常にオプションであるとは限りません。たとえば、式を構成ファイルに入れたり、別のプログラムに渡したりする必要がある場合があります。しかし、覚えておく価値があります。たとえば、このような否定を使用できる場合、式ははるかに単純になります。

于 2009-01-21T16:57:34.837 に答える