
1行に6つの値を持つタイムスタンプを持つログファイルがあり、同じ値を持つ連続行を削除し(タイムスタンプを無視して)、各反復セットの最初の行と最後の行を保持してデータ量を減らしたいと思います。 bashスクリプトを使用する方が良いです。魔法sed
やawk
命令の組み合わせでなければなりません。
ファイルを複数回解析する必要がある場合でも、一度に3行ずつ読み、中間行を削除するのが良い解決策です。
ソースファイル:
1447790360 99999 99999 20.25 20.25 20.25 20.50
1447790362 20.25 20.25 20.25 20.25 20.25 20.50
1447790365 20.25 20.25 20.25 20.25 20.25 20.50
1447790368 20.25 20.25 20.25 20.25 20.25 20.50
1447790371 20.25 20.25 20.25 20.25 20.25 20.50
1447790374 20.25 20.25 20.25 20.25 20.25 20.50
1447790377 20.25 20.25 20.25 20.25 20.25 20.50
1447790380 20.25 20.25 20.25 20.25 20.25 20.50
1447790383 20.25 20.25 20.25 20.25 20.25 20.50
1447790386 20.25 20.25 20.25 20.25 20.25 20.50
1447790388 20.25 20.25 99999 99999 99999 99999
1447790389 99999 99999 20.25 20.25 20.25 20.50
1447790391 20.00 20.25 20.25 20.25 20.25 20.50
1447790394 20.25 20.25 20.25 20.25 20.25 20.50
1447790397 20.25 20.25 20.25 20.25 20.25 20.50
1447790400 20.25 20.25 20.25 20.25 20.25 20.50
望ましい結果:
1447790360 99999 99999 20.25 20.25 20.25 20.50
1447790362 20.25 20.25 20.25 20.25 20.25 20.50
1447790386 20.25 20.25 20.25 20.25 20.25 20.50
1447790388 20.25 20.25 99999 99999 99999 99999
1447790389 99999 99999 20.25 20.25 20.25 20.50
1447790391 20.00 20.25 20.25 20.25 20.25 20.50
1447790394 20.25 20.25 20.25 20.25 20.25 20.50
1447790400 20.25 20.25 20.25 20.25 20.25 20.50
答え1
uniqは(一種の)完璧なツールです。デフォルトでは、uniqではコレクションの最初の行を保持/表示できますが、最後の行は維持/表示できません。
uniqには、最初のいくつかのフィールドをスキップできる-fフラグがあります。
トップユニークから:
-f, --skip-fields=N
avoid comparing the first N fields
-s, --skip-chars=N
avoid comparing the first N characters
A field is a run of blanks (usually spaces and/or TABs), then non-blank characters. Fields are skipped before chars.
uniq -c を使用してカウントを表示し、uniq が実行する操作を確認する例:
-bash-4.2$ uniq -c -f 1 original_file
1 1447790360 99999 99999 20.25 20.25 20.25 20.50
9 1447790362 20.25 20.25 20.25 20.25 20.25 20.50
1 1447790388 20.25 20.25 99999 99999 99999 99999
1 1447790389 99999 99999 20.25 20.25 20.25 20.50
1 1447790391 20.00 20.25 20.25 20.25 20.25 20.50
3 1447790394 20.25 20.25 20.25 20.25 20.25 20.50
良い。欲しいものにとても近いです。そしてそれは簡単です。しかし、グループの最後の一致行がありません。 。 。 。
この問題については、uniqのグループ化オプションも興味深いです。 。 。
--group[=METHOD]
show all items, separating groups with an empty line METHOD={separate(default),prepend,append,both}
-D, --all-repeated[=METHOD]
print all duplicate lines groups can be delimited with an empty line METHOD={none(default),prepend,separate}
たとえば、グループごとの uniq です。 。 。
-bash-4.2$ uniq --group=both -f 1 original_file
1447790360 99999 99999 20.25 20.25 20.25 20.50
1447790362 20.25 20.25 20.25 20.25 20.25 20.50
1447790365 20.25 20.25 20.25 20.25 20.25 20.50
1447790368 20.25 20.25 20.25 20.25 20.25 20.50
1447790371 20.25 20.25 20.25 20.25 20.25 20.50
1447790374 20.25 20.25 20.25 20.25 20.25 20.50
1447790377 20.25 20.25 20.25 20.25 20.25 20.50
1447790380 20.25 20.25 20.25 20.25 20.25 20.50
1447790383 20.25 20.25 20.25 20.25 20.25 20.50
1447790386 20.25 20.25 20.25 20.25 20.25 20.50
1447790388 20.25 20.25 99999 99999 99999 99999
1447790389 99999 99999 20.25 20.25 20.25 20.50
1447790391 20.00 20.25 20.25 20.25 20.25 20.50
1447790394 20.25 20.25 20.25 20.25 20.25 20.50
1447790397 20.25 20.25 20.25 20.25 20.25 20.50
1447790400 20.25 20.25 20.25 20.25 20.25 20.50
その後、grepを介して各空行の前後の行を見つけて、空行を削除します。
-bash-4.2$ uniq --group=both -f 1 original_file |grep -B1 -A1 ^$ |grep -Ev "^$|^--$"
1447790360 99999 99999 20.25 20.25 20.25 20.50
1447790362 20.25 20.25 20.25 20.25 20.25 20.50
1447790386 20.25 20.25 20.25 20.25 20.25 20.50
1447790388 20.25 20.25 99999 99999 99999 99999
1447790389 99999 99999 20.25 20.25 20.25 20.50
1447790391 20.00 20.25 20.25 20.25 20.25 20.50
1447790394 20.25 20.25 20.25 20.25 20.25 20.50
1447790400 20.25 20.25 20.25 20.25 20.25 20.50
ダダダ!良い。
答え2
awk
ライナーに付属:
awk '{n=$2$3$4$5$6$7}l1!=n{if(p)print l0; print; p=0}l1==n{p=1}{l0=$0; l1=n}END{print}' file
ポイントは、複数の変数を操作することです。n
最初のフィールドを除くすべてのフィールドを現在の行に保存すると、前の行と前のすべての行がl1
同じになります。l0
これはp
、前の行が印刷されたかどうかを示すフラグです。
答え3
Perlが構造に来ます:
perl -ne '($t, $r) = /([0-9]+\s+)(.*)/;
print "$pt$p\n$_" if $r ne $p;
$p = $r;
$pt = $t;
}{
print $t, $r' input-file \
| sort -nu | tail -n+2
-n
入力を1行ずつ読みます。$t
$r
「残り」はタイムスタンプにスペースを加えたものです。$p
以前のブレーキで、$pt
以前のタイムスタンプです。- 最後の行は常に印刷されます。
Perlはいくつかの行を2回印刷するため、sort -nu
重複した内容は削除する必要があります。tail
最初の空行を削除します。
答え4
sed -e:t -e'$!{1N;N;s/\( .*\)\(\n[^ ]*\1\)\{2\}$/\1\2/;tt' -e'P;D;}' <in >out
...それはうまくいきます。これは、2番目のスペースで区切られたフィールドから始まり、同じと見なされる一連の3つの入力ラインから2番目の入力ラインを再帰的に置き換えます。そうすることができなくなるまで、置き換える各入力ラインを置き換えるために、他の入力ラインを引き続き描画します。同様の3行が一致しない場合にのみ、P
バッファの最初の行を印刷してから削除し、残りのD
2行と次の入力行に再試行するためにループバックします。
GNUまたはBSDの使用sed
:
sed -Ee:t -e'1N;$!N;s/( .*)(\n[^ ]*\1){2}$/\1\2/;tt' -eP\;D <in >out
1447790360 99999 99999 20.25 20.25 20.25 20.50
1447790362 20.25 20.25 20.25 20.25 20.25 20.50
1447790386 20.25 20.25 20.25 20.25 20.25 20.50
1447790388 20.25 20.25 99999 99999 99999 99999
1447790389 99999 99999 20.25 20.25 20.25 20.50
1447790391 20.00 20.25 20.25 20.25 20.25 20.50
1447790394 20.25 20.25 20.25 20.25 20.25 20.50
1447790400 20.25 20.25 20.25 20.25 20.25 20.50