web-dev-qa-db-ja.com

Bashの正規表現の問題:[^ negate]が機能しないようです

Bashでls /directory | grep '[^term]'を実行すると、grepコマンドが何らかの理由で無視されているかのように、通常のリストが表示されます。 egrepでも同じことを試しましたが、二重引用符と単一引用符でそれを使おうとしましたが、より良い結果は得られませんでした。 ls /directory | grep '^[term]を試してみると、期待どおり、termで始まるすべてのエントリが表示されます。

私はこのコマンドをオンラインエディターで試してみました test my regex を実行でき、正常に機能しました。しかし、バッシュではありません。したがって、シミュレーションでは機能しますが、実際には機能しません。

私はCrunchbang Linux 10で作業しています。このような基本的なレベルで実行できず、何時間もの時間を浪費することは本当にイライラするので、これが十分な情報であり、すべてのヒントを楽しみにしています。

8
erch

あなたがしたいことが起こっていると確信していますか? ls /directory | grep '[^term]'を実行すると、基本的に文字t e r mではなくgreppingになります。つまり、ファイルの名前に他の文字が含まれている場合でも、lsの出力には表示されます。たとえば、次のディレクトリを取ります。

$ ls
alpha  brave  bravo  charlie  delta

ls |grep '^[brav]'を実行すると、次のようになります。

$ ls |grep '^[brav]'
alpha
brave
bravo

ご覧のとおり、bravebravoを取得しただけでなく、alphaも取得しました。これは、文字クラス[]がそのリストから文字を取得するためです。

したがって、ls |grep '[^brav]'を実行すると、名前に文字b r a v anywhereが含まれていないすべてのファイルが取得されます。

$ ls |grep '[^brav]'
alpha
bravo
brave
charlie
delta

すべてのファイルに少なくとも文字クラスに含まれていないone文字が含まれていたため、ディレクトリリスト全体が含まれていることに気づいた場合。

したがって、Kanvuanzaが言ったように、文字t e r mではなく「term」の逆をgrepするには、grep -vを使用する必要があります。

例えば:

$ ls |grep -v 'brav'
alpha
charlie
delta

また、クラスに文字が含まれるファイルが不要な場合は、grep -v '[term]'を使用します。これにより、これらの文字を含むファイルが表示されなくなります。 (カンブアンザの答え)

例えば:

$ ls |grep -v '[brav]'

ご覧のとおり、このディレクトリ内のすべてのファイルにはそのクラスからの少なくとも1つの文字が含まれているため、ファイルはリストされていません。

補遺:

PCREを使用すると、正規表現だけを使用して否定式を使用してフィルターをかけることができるということを追加したかったのです。これを行うには、否定的な先読み正規表現(?!<regex>)を使用します。

したがって、上記の例を使用すると、grepフラグを使用せずに、次のようにして必要な結果を得ることができます。

$ ls | grep -P '^(?!brav)'
alpha
charlie
delta

その正規表現を分解するには、最初に^の行の先頭で照合し、次にbravに一致しない文字列を探して、その後に続きます。 alphacharlie、およびdeltaのみが一致するため、出力されるのはこれらだけです。

12
prateek61

grep -vフラグはあなたが望むことをしていると思います。 man page から:

-v, --invert-match
    Invert the sense of matching, to select non-matching lines.

ls /directory | grep -v [term]を使用して、一致しない行を印刷できます。

3
Pedro Lacerda