120

私は、文字Ui\.が続かない、Lineまたは文字だけでさえないすべてのインスタンスをgrepしようとしていますL

別の文字列が続かない特定の文字列のすべてのインスタンスを検索するための正規表現を作成する適切な方法は何ですか?

先読みの使用

grep "Ui\.(?!L)" *
bash: !L: event not found


grep "Ui\.(?!(Line))" *
nothing
4

6 に答える 6

167

あなたが求めているものであるネガティブ先読みには、標準よりも強力なツールが必要ですgrep。PCRE対応のgrepが必要です。

GNUを使用している場合grep、現在のバージョンはオプションをサポートしています。-Pまたは--perl-regexp、必要な正規表現を使用できます。

(十分に新しいバージョンの)GNUがない場合はgrep、を取得することを検討してackください。

于 2012-02-08T18:08:18.793 に答える
44

あなたの問題の一部に対する答えはここにあります、そしてackは同じように振る舞います: エラーを与えるAckと否定的な先読み

grepに二重引用符を使用しています。これにより、bashは「!履歴展開コマンドとして解釈」できます。

パターンをSINGLE-QUOTESでラップする必要があります。 grep 'Ui\.(?!L)' *

ただし、標準でのネガティブな先読みの問題に対処するには、@JonathanLefflerの回答grepを参照してください。

于 2013-06-20T21:04:55.583 に答える
12

grepを使用して標準のネガティブ先読みを実行することはおそらくできませんが、通常は「逆」スイッチ「-v」を使用して同等の動作を得ることができるはずです。これを使用して、一致させたいものを補完する正規表現を作成し、それを2つのgrepsにパイプすることができます。

問題の正規表現については、次のようなことを行う可能性があります

grep 'Ui\.' * | grep -v 'Ui\.L'
于 2014-11-01T09:43:09.290 に答える
6

否定の先読みをサポートしない正規表現の実装を使用する必要があり、余分な文字*を一致させてもかまわない場合は、否定の文字クラス[^L]交互|、および文字列アンカーの終わりを$使用できます。

あなたの場合grep 'Ui\.\([^L]\|$\)' *は仕事をします。

  • Ui\.興味のある文字列と一致します

  • \([^L]\|$\)または以外の任意の1文字Lに一致するか、行末に一致します:[^L]または$

複数のキャラクターを除外したい場合は、さらに多くの代替と否定をスローする必要があります。a後に続くものを見つけるにはbc

grep 'a\(\([^b]\|$\)\|\(b\([^c]\|$\)\)\)' *

a後にnotbが続く、または行の終わりが続く:athen[^b]または$)または(aその後bにnotcが続くか、または行の終わりが続く:athen b、then[^c]または$

この種の表現は、短い文字列でもかなり扱いにくく、エラーが発生しやすくなります。式を生成するために何かを書くこともできますが、否定的な先読みをサポートする正規表現の実装を使用する方がおそらく簡単でしょう。

*実装が非キャプチャグループをサポートしている場合は、余分な文字をキャプチャすることを回避できます。

于 2016-01-06T03:50:14.440 に答える
2

少なくとも、「Ui」の後に「L」文字が必要ない場合。あなたは本当にPCREを必要としません。

    grep -E 'Ui\.($|[^L])' *

ここでは、「Ui」の特殊なケースと一致するようにしました。行の終わりに。

于 2021-06-09T14:15:45.387 に答える
1

grepが-Pまたは--perl-regexpをサポートしておらず、PCRE対応のgrep(「pcregrep」など)をインストールできる場合は、Perl互換の正規表現を受け入れるためにGNUgrepなどのコマンドラインオプションは必要ありません。式、あなたはただ走る

pcregrep "Ui\.(?!Line)"

例「Ui。(?!(Line))」のように、「Line」に別のネストされたグループは必要ありません。上記のように、外側のグループで十分です。

否定的なアサーションを探す別の例を挙げましょう。「ipset」によって返される行のリストがあり、各行は行の中央にあるパケットの数を示しており、パケットがゼロの行は必要ありません。走る:

ipset list | pcregrep "packets(?! 0 )"

perl互換の正規表現が好きで、perlはあるが、pcregrepがない場合、またはgrepが--perl-regexpをサポートしていない場合は、grepと同じように機能する1行のperlスクリプトを使用できます。

perl -e "while (<>) {if (/Ui\.(?!Lines)/){print;};}"

Perlはgrepと同じようにstdinを受け入れます。

ipset list | perl -e "while (<>) {if (/packets(?! 0 )/){print;};}"
于 2017-04-22T06:26:22.753 に答える