Bashからファイルの特定の行を削除したいです。
sed
現在私がやっていることは、この行を削除するために行番号を取得して渡すことです。
awk '/qr/{ print NR; exit }' test | sed -i "${1}d" test
ウィジェットはawk
正常に動作しますが、この状態ではsed
ウィジェットはファイル(testという名前)の内容をすべて削除します。
ただし、変数なしでこれを実行すると、次のようになります。
sed -i '1d' test
良い結果。
私は何が間違っていましたか?
答え1
${1}
現在、コンテキストの最初の引数に置き換えられ、awk
例の出力から何も読みません。
awk
sumを維持したい場合、sed
1つの方法はの出力をawk
変数に格納することです。
line=$(awk '/qr/{ print NR; exit }' test); sed -i "${line}d" test
ただし、ファイルに「qr」を含む行がないと、正しく機能しません。
より良いアプローチは、以下を使用することですsed
。
sed -i "/qr/d" test
ただし、これにより、最初の行だけでなく、一致するすべての行も削除されます。
AWK(またはgawk
GNU実装、バージョン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;}