お気に入り
私が持っている場合:
1st line (keep)
2nd line (keep)
3rd line (keep)
4rth lines (delete)
5th (del)
6th (keep)
7nth (keep)
8th lines (keep)
9th (del)
10th (del)
11th (keep)
12th (keep)
13th (keep)
14th (del)
15th (del)
等....
試してください:
awk '(NR-1)%5<3' file
例えば:
$ awk '(NR-1)%5<3' file
1st line (keep)
2nd line (keep)
3rd line (keep)
6th (keep)
7nth (keep)
8th lines (keep)
11th (keep)
12th (keep)
13th (keep)
コマンド(NR-1)%5<3
は、awk
に、(NR-1)%5<3
がtrueである行を出力するように指示します。 awk
では、NR
は行番号で、最初の行は1
としてカウントされます。ファイルの5行ごとに、そのステートメントは最初の3行に当てはまります。
簡単なコマンドは次のとおりです。
awk '{if((NR-1) % 5<=2){print $0}}' file
最初の3行だけを5行ずつ印刷します。 (NR-1)%5
は0 1 2 3 4
のような出力を提供し、最初の3行は2以下であるため、出力するだけです。
内容のファイルがあります:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
出力は次のとおりです。
1
2
3
6
7
8
11
12
13
または、コメントで提案されているように、使用できます:
awk '(NR - 1) % 5 <= 2' file
基本的に、あなたはawkで 'Fizz-Buzz'のようなものを望みます...
awk '{ if (i++%5 < 3) print $0;}'
この作品を表示するには...
for x in 1 2 3 4 5 6 7 8 9 10 ; do echo $x; done |
awk '{ if (i++%5 < 3) print $0;}'
ファイルの名前が 'mybigfile.csv'の場合、
awk '{ if (i++%5 < 3) print $0;}' < mybigfile.csv > mybigfile-123.csv
これは、GNU sed
を使用して解決できます。
_sed '4~5,5~5d' file
_
これは、sed標準にGNU固有の拡張機能を使用しているため、たとえば、 BSDはmacOS上で動作します。ただし、GNU sedはbrew
を使用してmacOSにインストールでき、その後gsed
として使用できます。LinuxではGNUデフォルトはsedです。
これにより、5行ごとに4行目から5行目までに収まらないすべての行が印刷されます。より明確な例:_sed '3~10,6~10d'
_ 3行目から6行目までを削除して、10行の各グループの選択行1、2、7、8、9、10を塗りつぶします。
トップ投票の回答は、awk '(NR-1)%5<3'
の使用を提案しています。私のマシンでは、1から200万までの数字を含むファイルで、これは約0.6秒かかりますが、この回答のsedソリューションは約0.35秒かかります。 sedは一般に単純なツールであるため、これは合理的であり、したがって、より複雑であるがフル機能を備えたawkよりも高速に動作できます。
ファイルから特定の行のパターンをマスクするための一般的なソリューション:
_#!/bin/sh
# The pattern is given on the command line.
pattern=$1
# The period is simply the length of the pattern.
period=${#pattern}
# Use bc to convert the binary pattern to an integer.
mask=$( printf 'ibase=2; %s\n' "$pattern" | bc )
awk -v mask="$mask" -v period="$period" '
BEGIN { p = lshift(1, period-1) }
and(rshift(p, (FNR-1) % period), mask)'
_
これは、非標準関数and()
(ビットごとのAND)、rshift()
およびlshift()
(ビットごとの右および左シフト)を実装するawk
に依存しています。どちらもGNU awk
とawk
の一部のBSD実装はありますが、mawk
ではありません。
これは、周期的な周期と各周期内のどの行を保持またはマスクするかを表す2進数であるパターンを取ります。 _1
_は「保持」を意味し、_0
_は「削除」を意味します。
例:質問に適用する必要がある行のパターンは_11100
_です。これは、「5行のセットごとに、最初の3行を保持し、他の行を削除する」ことを意味します。
_01001000
_を使用すると、8行ごとに2行目と5行目以外がすべて削除されます。
awk
プログラムは、次のようにBEGIN
ブロックなしで書くこともできます。
_and(lshift(1, (period-1) - (FNR-1) % period), mask)
_
_(period-1) - (FNR-1) % period
_の位置による1の左シフトは、2の累乗の計算と同じですが、awk
は正確な整数演算ではなく浮動小数点演算を使用して演算を行うため、lshift()
を使用しています。
コードはパターンのバイナリ表現に依存しているため、非常に長いパターンはうまく機能しない可能性があります。
テスト:
削除したい行を削除する:
_$ sh script.sh 11100 <file
1st line (keep)
2nd line (keep)
3rd line (keep)
6th (keep)
7nth (keep)
8th lines (keep)
11th (keep)
12th (keep)
13th (keep)
_
パターンを反転させる:
_$ sh script.sh 00011 <file
4rth lines (delete)
5th (del)
9th (del)
10th (del)
14th (del)
15th (del)
_
以下のコマンドで試してみましたが、うまくいきました
for((i=1;i<=20;i++)); do j=$(($i+2)); sed -n ''$i','$j'p' filename;i=$(($j+2)); done
出力
1st line (keep)
2nd line (keep)
3rd line (keep)
6th (keep)
7nth (keep)
8th lines (keep)
11th (keep)
12th (keep)
13th (keep)