一部の正規表現フレーバーでは、[負の] ゼロ幅アサーション (先読み/後読み) がサポートされていません。
これにより、除外を述べることが非常に困難 (不可能?) になります。たとえば、「「foo」を含まないすべての行」は次のようになります。
^((?!foo).)*$
ルックアラウンドをまったく使用せずに同じことを達成できますか (複雑さとパフォーマンスの問題は今のところ脇に置いておきます)。
一部の正規表現フレーバーでは、[負の] ゼロ幅アサーション (先読み/後読み) がサポートされていません。
これにより、除外を述べることが非常に困難 (不可能?) になります。たとえば、「「foo」を含まないすべての行」は次のようになります。
^((?!foo).)*$
ルックアラウンドをまったく使用せずに同じことを達成できますか (複雑さとパフォーマンスの問題は今のところ脇に置いておきます)。
更新:@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 "^\(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
正規表現内のシーケンスを除外しようとしている、独自の正規表現除外ソリューションを探しているこの質問に出くわしました。
この状況に対する私の最初の反応: たとえば、「「foo」が含まれていないすべての行」 は、grep で一致するオプションの -v invert を単純に使用することでした。
grep -v foo
これは、「foo」に一致しないファイル内のすべての行を返します
単純すぎて質問を読み違えてしまった感が強い…。
通常、foo を探して、正規表現一致の結果をクライアント コードから反転させることができます。
簡単な例として、文字列に特定の文字のみが含まれていることを検証したいとします。
次のように記述できます。
^[A-Za-z0-9.$-]*$
true
結果を有効なものとして受け入れるか、次のようにします。
[^A-Za-z0-9.$-]
false
結果を有効なものとして受け入れます。
もちろん、これは常にオプションであるとは限りません。たとえば、式を構成ファイルに入れたり、別のプログラムに渡したりする必要がある場合があります。しかし、覚えておく価値があります。たとえば、このような否定を使用できる場合、式ははるかに単純になります。