ファイルから 1 つまたは複数の特定の行番号を削除したいと考えています。sedを使用してこれを行うにはどうすればよいですか?
7 に答える
5 行目から 10 行目と 12 行目を削除する場合:
sed -e '5,10d;12d' file
これにより、結果が画面に出力されます。結果を同じファイルに保存する場合:
sed -i.bak -e '5,10d;12d' file
これにより、変更されていないファイルが として保存されfile.bak
、指定された行が削除されます。
注: 行番号は 1 から始まります。ファイルの最初の行は 0 ではなく 1 です。
とawkも
awk 'NR!~/^(5|10|25)$/' file
$ cat foo
1
2
3
4
5
$ sed -e '2d;4d' foo
1
3
5
$
これは、多くの場合、アンチパターンの兆候です。行番号を生成したツールは、行をすぐに削除するツールに置き換えることができます。例えば;
grep -nh error logfile | cut -d: -f1 | deletelines logfile
(deletelines
必要だと想像しているユーティリティはどこにありますか)は次と同じです
grep -v error logfile
そうは言っても、本当にこのタスクを実行する必要がある場合はsed
、行番号のファイルから簡単なスクリプトを生成できます。ユーモラスなことに (少し紛らわしいかもしれませんが)、 でこれを行うことができますsed
。
sed 's%$%d%' linenumbers
これは、行ごとに 1 つの行番号のファイルを受け入れ、標準出力に同じ行番号を生成し、d
それぞれの後に追加します。これは有効なsed
スクリプトで、ファイルに保存したり、(一部のプラットフォームでは) 別のsed
インスタンスにパイプしたりできます。
sed 's%$%d%' linenumbers | sed -f - logfile
一部のプラットフォームでは、sed -f
はオプション引数が標準入力を意味することを理解していないため-
、スクリプトを一時ファイルにリダイレクトし、完了したらクリーンアップする/dev/stdin
か/proc/$pid/fd/1
、OS (またはシェル) があります。
いつものように、オプション-i
の前に追加して、標準出力に結果を生成する代わりに、ターゲット ファイルをその場で編集することができます。*BSDish プラットフォーム (OSX を含む) では、明示的な引数も指定する必要があります。一般的なイディオムは、空の引数を指定することです。.-f
sed
-i
-i ''
awk による一般化を提案したいと思います。
ファイルが固定サイズのブロックで構成されていて、削除する行がブロックごとに繰り返される場合、awk はこのような方法で正常に動作します。
awk '{nl=((NR-1)%2000)+1; if ( (nl<714) || ((nl>1025)&&(nl<1029)) ) print $0}'
OriginFile.dat > MyOutputCuttedFile.dat
この例では、ブロックのサイズは 2000 で、行 [1..713] と [1026..1029] を印刷したいと考えています。
NR
awk が現在の行番号を格納するために使用する変数です。%
2 つの整数の除算の余り (または剰余) を返します;nl=((NR-1)%BLOCKSIZE)+1
ここで、変数nlに現在のブロック内の行番号を書き込みます。(下記参照)||
and&&
は、論理演算子ORおよびANDです。print $0
全行を書き込みます
Why ((NR-1)%BLOCKSIZE)+1:
(NR-1) We need a shift of one because 1%3=1, 2%3=2, but 3%3=0.
+1 We add again 1 because we want to restore the desired order.
+-----+------+----------+------------+
| NR | NR%3 | (NR-1)%3 | (NR-1)%3+1 |
+-----+------+----------+------------+
| 1 | 1 | 0 | 1 |
| 2 | 2 | 1 | 2 |
| 3 | 0 | 2 | 3 |
| 4 | 1 | 0 | 1 |
+-----+------+----------+------------+