次のような大きなCSVファイルがあります。
SomeData,SomeData,1,SomeData
SomeData,SomeData,1,SomeData
SomeData,SomeData,2,SomeData
SomeData,SomeData,3,SomeData
SomeData,SomeData,1,SomeData
SomeData,SomeData,1,SomeData
SomeData,SomeData,1,SomeData
SomeData,SomeData,1,SomeData
SomeData,SomeData,2,SomeData
SomeData,SomeData,3,SomeData
SomeData,SomeData,4,SomeData
SomeData,SomeData,5,SomeData
SomeData,SomeData,1,SomeData
SomeData,SomeData,1,SomeData
SomeData,SomeData,1,SomeData
SomeData,SomeData,1,SomeData
3番目の値がセットの一部である行のみを含む新しいcsvファイルを作成したいと思います。つまり、下の行の3番目のフィールドに高い値がある場合は、両方の行を含めたいと思います。
したがって、上記の例では、2〜4行と8〜12行のみを新しいファイルに保存しようとしています。
grep
このパターンを見つける方法を見つけようとしています。
どんなアイデアがありますか?
ありがとう
答え1
CSVファイルは難しいです。カンマを含むことができる適切に引用されたデータフィールドを想定すると、Somedata
区切り文字をタブ文字(ほとんどの最新のシェルで)のようにデータに表示されないものに置き換えることができます$'\t'
(操作内容に変更できます)。 。データフィールドにカンマがない場合は、csvformat
ここのビットをスキップします。
使用csvkit
:
$ csvformat -D$'\t' data.csv
SomeData SomeData 1 SomeData
SomeData SomeData 1 SomeData
SomeData SomeData 2 SomeData
SomeData SomeData 3 SomeData
SomeData SomeData 1 SomeData
etc.
その後、awk
グループを見つける実際の操作を実行するスクリプトに渡すことができます。
NR > 1 && $3 == count + 1 {
# This line is part of the set.
++count; # We expect this value on the next line.
++set_size; # This is the number of lines in the set.
# Output previous line and remember this line.
print previous_line;
previous_line = $0;
# Continue with next line.
next;
}
set_size > 0 && $3 != count + 1 {
# This line is not part of the set, but we're currently tracking a
# set. This means that the set ended, so output the last line of
# the set.
print previous_line;
set_size = 0;
}
{
# This line might be part of the next set.
count = $3;
previous_line = $0
}
実行してください:
$ csvformat -D$'\t' data.csv | awk -F$'\t' -f script.awk
SomeData SomeData 1 SomeData
SomeData SomeData 2 SomeData
SomeData SomeData 3 SomeData
SomeData SomeData 1 SomeData
SomeData SomeData 2 SomeData
SomeData SomeData 3 SomeData
SomeData SomeData 4 SomeData
SomeData SomeData 5 SomeData
その後、標準のカンマ区切り形式に戻ります。
$ csvformat -D$'\t' data.csv | awk -F$'\t' -f script.awk | csvformat -d$'\t'
SomeData,SomeData,1,SomeData
SomeData,SomeData,2,SomeData
SomeData,SomeData,3,SomeData
SomeData,SomeData,1,SomeData
SomeData,SomeData,2,SomeData
SomeData,SomeData,3,SomeData
SomeData,SomeData,4,SomeData
SomeData,SomeData,5,SomeData
データフィールド内のデータにカンマがない場合は、csvformat
完全に省略できます。
$ awk -F',' -f script.awk data.csv
SomeData,SomeData,1,SomeData
SomeData,SomeData,2,SomeData
SomeData,SomeData,3,SomeData
SomeData,SomeData,1,SomeData
SomeData,SomeData,2,SomeData
SomeData,SomeData,3,SomeData
SomeData,SomeData,4,SomeData
SomeData,SomeData,5,SomeData
答え2
データがこの処理にdatafile
使用可能なファイルにあるとします。 (1行のコンテキストのみを処理するためawk
使用できません。)grep
awk -F, '
# Initially we are not in a block
BEGIN { inblock=0 }
# If the third field is greater than that on the previous line, print
# it. But if we were not already in a block then print the saved line
# too - and mark that we are now in a block
NR>1 && $3>third { if (!inblock) { print line; inblock=1 } print $0 }
# If we are in a block and the third field is smaller that the previous
# line value, drop out of the block
inblock && $3<=third { inblock=0 }
# Save the values each time around
{third=$3; line=$0 }
' datafile
SomeData,SomeData,1,SomeData
SomeData,SomeData,2,SomeData
SomeData,SomeData,3,SomeData
SomeData,SomeData,1,SomeData
SomeData,SomeData,2,SomeData
SomeData,SomeData,3,SomeData
SomeData,SomeData,4,SomeData
SomeData,SomeData,5,SomeData