bashでawkを使用して行番号を正しく検索し、sedを使用して削除する方法は?

bashでawkを使用して行番号を正しく検索し、sedを使用して削除する方法は?

Bashからファイルの特定の行を削除したいです。

sed現在私がやっていることは、この行を削除するために行番号を取得して渡すことです。

awk '/qr/{ print NR; exit }' test | sed -i "${1}d" test

ウィジェットはawk正常に動作しますが、この状態ではsedウィジェットはファイル(testという名前)の内容をすべて削除します。

ただし、変数なしでこれを実行すると、次のようになります。

sed -i '1d' test

良い結果。

私は何が間違っていましたか?

答え1

${1}現在、コンテキストの最初の引数に置き換えられ、awk例の出力から何も読みません。

awksumを維持したい場合、sed1つの方法はの出力をawk変数に格納することです。

line=$(awk '/qr/{ print NR; exit }' test); sed -i "${line}d" test

ただし、ファイルに「qr」を含む行がないと、正しく機能しません。

より良いアプローチは、以下を使用することですsed

sed -i "/qr/d" test

ただし、これにより、最初の行だけでなく、一致するすべての行も削除されます。

AWK(またはgawkGNU実装、バージョン4.1.0以降)は上記と同じです。

gawk -i inplace '!/qr/' test

または、最初のインスタンスのみを置き換えるには

gawk -i inplace '/qr/ && !i { i++; next; } 1' test

答え2

次の入力ファイルが与えられた場合:

$ cat file
foo
qr
bar

本当にこの方法を使用したい場合は、次のようにします(-iそうでなければsedの効果を見ることができます)。

$ awk '/qr/{print NR; exit}' file | xargs -n 1 -I {} sed '{}d' file
foo
bar

しかし、もちろんこれは無意味なxargs + sedパイプラインなので、やるべきことは次のとおりです。

awk '!f && /qr/{f=1; next} 1' file > tmp && mv tmp file

または、それをサポートする最新バージョンのgawkを使用してください。

awk -i inplace '!f && /qr/{f=1; next} 1' file

答え3

パターンの最初の発生のみを削除すると仮定すると、次のようにawk正確に使用できます。

awk '/qr/{if (!i++) next}1' test

これにより、1最初の一致する行()を除くすべての行が印刷されます/qr/iまだゼロなので、next「印刷」ジョブが適用される前にコマンドが実行されます)。

「内部」編集機能が必要な場合sed -iそしてGNU> 4.1.0を使用している場合は、awk"inplace"拡張を使用できます。

awk -i inplace '/qr/{if (!i++) next}1' test

答え4

一致する最初の行のみを削除するには

sed  "0,/qr/{/qr/d;}" file 

-iテスト後、nlineと入力してください。

これは、最初の行から最初の一致までのアドレスのみを処理します。qr

0,/qr/ 

そのアドレス範囲に含まれるすべての行を削除します。qr

{/qr/d;}

関連情報