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


8

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

私はこのコマンドをオンラインエディターで試してみました。正規表現テストすると、正常に機能しました。しかし、バッシュではありません。したがって、シミュレーションでは機能しますが、実際には機能しません。

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


タイトルのネガが原因で混乱しています。greptermで始まる行にしたいですか。または、用語をまったく含まない行をgrepしたいですか?
Bernhard

@Bernhard:角かっこ内に用語がないリストが欲しい。正確に「期間」である必要はありません!私が理解している限り、[^ abc]は、a、b、c、またはそれらの任意の組み合わせを含むものはリストに含めないことを意味します。
2013年

回答:


12

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

$ ls
alpha  brave  bravo  charlie  delta

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

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

あなたが見ることができるように、私が手に入れただけでなく、bravebravo私はまた、得たalpha文字クラスがあるため[]、そのリストから任意の文字を取得します。

したがって、実行するls |grep '[^brav]'と、名前のどこかにbravという文字が含まれていないすべてのファイルが取得されます。

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

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

したがって、Kanvuanzaが言ったように、「term」の逆をgrepするには、t e r mを使用して文字を実行する必要があります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それらが印刷されているだけですので、一致しています。


1
つまり、ファイルの名前に他の文字が含まれている場合でも、lsの出力には表示されます。これはかなりの数の質問に答えます!:)だから今のところ最良の方法は-vオプションのようです。ご協力ありがとうございました!この質問は私の午後を本当に台無しにしました、そこであなたの答えは私の夜を明るくします!
2013年

の+1 negative look-ahead regex
Abhishek Kashyap

3

そのgrep -vフラグはあなたがやりたいことをしていると思います。manページから:

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

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


私はこのオプションを知っていますが、[^ xyz]が[xyz]の反対であり、どのような場合でも機能するはずであると想定するのは間違っていますか?また、このような基本的なレベルのどこでも設定を編集することは避けたいです。反転オプションの使用や設定の編集は確かに良い方法ですが、私が理解している限り、これは箱から出さなくても機能するはずです。
2013年

私はあなたが正しいと思います、それはクラス否定の一般的な表記法です(つまり。[^abc]しかし、いくつかの標準的なものを除いて、grepがクラス否定をサポートしていないことは確かです(例[[:^digits:]]:)。否定のGrepサポートは恐ろしいです!
ペドロラセルダ2013年

否定のGrepサポートは恐ろしいです!そして、これはケーキの本当のアイシングであるヒントです。私はegrepで同じ問題を抱えており、現時点では[少なくとも私には一見]より高度なコマンドを使用することにはほど遠いです。より良い結果とより少ない頭痛を提供するコマンドを提案できますか?
2013年

@ cellar.dweller、grepの文字クラスの処理は問題ありません。それはあなたが(誤)理解しているものとはまったく異なる何かを意味します。[abc]手段の一つabまたはc; [^abc]何を意味しますが、上記を。これは、ある1つの文字。
フォンブランド2013年

@ cellar.dweller:あなたの最大の問題は、正規表現、特に正規表現内の文字クラスの誤解だと思います。
2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.