bashで次から始めて、終わらない行をファイルから削除します。

bashで次から始めて、終わらない行をファイルから削除します。

特定の文字または文字セットで始まる行を削除する方法については、sedの例をたくさん読んでいましたが、それほど難しくありませんが、この例を解読することはできません。ファイル内の文字「i」で始まり、「.conf」で終わらない行をすべて削除したいと思います。

以下は例のリストです。

include /usr/local/choops/users/2488.conf
include /usr/local/cho
include /usr/local/choops/users/2492.conf
i
incl

上記の例で削除する3行は次のとおりです。

include /usr/local/cho
i
incl

それらは不完全であり、そこにはありません。

StackExchange、StackOverflow、その他のさまざまなフォーラムで、この例のいくつかのバリエーションを試しましたが、正しく理解できないようです。私が試したことは次のとおりです。

sed -i '/^i.*[^\.conf]$/d' /usr/local/choops/users/main.conf

sed -i '/^i.\*\[^\\.conf\]$/d' /usr/local/choops/users/main.conf

sed -i '/^i.*[^.conf]$/d' /usr/local/choops/users/main.conf

ここで、main.confは、上記のように.confファイルセットを一覧表示するファイルです。私はこれがあまりにも複雑ではないと思いましたが、これらのコマンドのどれも私には機能しないようです。さまざまなソースとsedの理解に基づいてコマンドを構築しました。どんな助けでも大変感謝します。とても混乱しています。

以下は私が望むものとは反対ですが、簡単だと思います。

sed -i 's/i.*.conf//' main.conf

答え1

同時に満たす必要がある2つの条項があります(「iで始まる」、「.confで終わらない」)。出力から行を除外するには、各句を個別にテストしてから組み合わせる必要があります。

入力例(「i」で始まらない追加の行を追加):

$ cat input.txt 
include /usr/local/choops/users/2488.conf
this line doesn't begin with i
include /usr/local/cho
this line doesn't begin with i but does end in .conf
include /usr/local/choops/users/2492.conf
i
incl

そしてperl

$ perl -ne 'print unless (/^i/ && ! /\.conf$/)' input.txt 
include /usr/local/choops/users/2488.conf
this line doesn't begin with i
this line doesn't begin with i but does end in .conf
include /usr/local/choops/users/2492.conf

そしてsed

$ sed -ne '/^i/ {/\.conf$/!d;};p' input.txt 
include /usr/local/choops/users/2488.conf
this line doesn't begin with i
this line doesn't begin with i but does end in .conf
include /usr/local/choops/users/2492.conf

または@seshoumaraが提案したように(おそらくより良いでしょう):

sed -e '/^i/ {/\.conf$/!d;}' input.txt

3つのバージョンすべてが出力から不要な行を削除し、他のすべての内容を印刷します。

答え2

行が「i」で始まる場合はtrue、行が「.conf」で終わらない場合はtrueという2つの条件があるようです。一度に検索するのではなく、2回にわたって検索してください。

sed -i '/^i/{/\.conf$/!d}' /usr/local/choops/users/main.conf

それともその逆なら否定してください。

sed -i '/^i.*\.conf$/!d' /usr/local/choops/users/main.conf

ポイントはエスケープする必要があります。それ以外の場合は、任意の文字を表す正規表現になります。

実際に試している「[^abc]」正規表現は、「a」、「b」、または「c」ではない単一文字を意味します。 「j」または「z」のいずれかです。この正規表現が何と一致していても、まだ単一の文字です。最後に、「[]」または「[^]」の文字は正規表現の意味を持つことはできず、リテラル文字のリストにすぎず、「.」は常にドットを意味するため、エスケープする必要はありません。しかし、//またはs///では、状況に応じてエスケープしたいです。

答え3

文字「i」で始まり、「.conf」で終わらないファイルのすべての行を削除したいと思います。

  • A「と言いましょう。文字で始まるi
  • B「と言いましょう。次に終わる.conf

使用ブール論理「AでBではない」条件に一致する行を削除すると言うことができます。

A . B'

また、これを「{AまたはBではない}の否定」として書き換えることもできます。

( A' + B'' )' = ( A' + B )'

これを使用すると、grepこれを次のように置き換えることができます。維持する(削除する代わりに)式に一致する行は次のとおりです。

( A' + B )

コードではこうなります。

grep -E '^[^i]|\.conf$'

実際には、まったく文字で始まらない行(つまり空白)も考慮する必要があります。

grep -E '^[^i]|\.conf$|^$'

サンプルファイルを使用すると、次の行を保持できます。

include /usr/local/choops/users/2488.conf
include /usr/local/choops/users/2492.conf

内部編集(煙とミラー)には一般的な規則が適用されるため、直接適用します。

grep ... file >file.tmp &&
    mv -f -- file.tmp file
rm -f -- file.tmp

答え4

begin with the letter "i" and DO NOT end with ".conf"awkを使用すると、指定した一致要件を削除したい行を識別するコードに簡単に変換できます。

$ awk '/^i/ && !/\.conf$/' file
include /usr/local/cho
i
incl

次に、維持したい行を取得するには、条件を無効にします。

$ awk '!(/^i/ && !/\.conf$/)' file
include /usr/local/choops/users/2488.conf
include /usr/local/choops/users/2492.conf

必要に応じて、次のように短縮できます。ドモーガンの法則到着する:

$ awk '!/^i/ || /\.conf$/' file
include /usr/local/choops/users/2488.conf
include /usr/local/choops/users/2492.conf

関連情報