大きなCSVがあり、インスタンスが30を超える場合は、名前フィールド($ 8)、中間名フィールド($ 9)、および姓フィールド($ 10)が同じレコードを削除したいと思います。
TYPE|10007|44|Not Available||||CHRISTINE||HEINICKE|||49588|2014-09-15|34
TYPE|1009|44|Not Available||||ELIZABETH||SELIGMAN|||34688|2006-02-12|69
TYPE|102004|44|Not Available||||JANET||OCHS|||11988|2014-09-15|1022
TYPE|1000005|44|Not Available||||KIMBERLY||YOUNG|||1988|2016-10-04|1082
これが私が今まで持っているものです:
awk -F"|" '++seen[tolower($8 || $9 || $10)] <= 30' foo.csv > newFoo.csv
答え1
私は、「単純なCSV」ファイル、つまり埋め込み区切り文字または埋め込み改行文字を含むフィールドを含まないファイルを扱っていると仮定します。
30項目を確認した後に表示される項目インスタンスを削除します。
awk -F '|' 'count[$8,$9,$10]++ < 30' file
また、これらのエントリの最初の30個のインスタンスを削除します。上記の方法を使用して計算し、フィルタリングと出力のためにファイルを再解析できます。
awk -F '|' '!output { ++count[$8,$9,$10]; next } count[$8,$9,$10] <= 30' file output=1 file
パラメータリストでファイルを2回参照し、変数を中間値output
に設定しました。1
その後、コードは「カウントモード」(コードの最初のブロック)から「フィルタと出力モード」(最初のブロック以降のテスト)に切り替わります。
使用しているキーを小文字に変更する必要がある場合は、読みやすくするために最初に別々に計算することをお勧めします。
awk -F '|' '
{ key = tolower($8) SUBSEP tolower($9) SUBSEP tolower($10) }
count[key]++ < 30' file
awk -F '|' '
{ key = tolower($8) SUBSEP tolower($9) SUBSEP tolower($10) }
!output { ++count[key]; next }
count[key] <= 30' file output=1 file
値は、この回答の最初の2つのコードスニペットと同じように、カンマで区切られたキーとして使用されるときに値の間に挿入されるSUBSEP
特別な区切り文字です。awk
答え2
これは、入力がファイルに保存され、パイプから出ていないと仮定し、入力ファイルを2回読み取る方法です。
awk -F'|' '
{ name = tolower($8 FS $9 FS $10) }
NR==FNR { nameCnts[name]++; next }
nameCnts[name] <= 30
' file file
または、パイプ入力とファイルで作業できるように、ファイルの内容を配列に保存します。
awk -F'|' '
{
name = tolower($8 FS $9 FS $10)
nameCnts[name]++
recs[NR] = $0
names[NR] = name
}
END {
for ( recNr=1; recNr<=NR; recNr++ ) {
name = names[recNr]
if ( nameCnts[name] <= 30 ) {
print recs[recNr]
}
}
}
' file
あるいは、パイプ入力またはファイルで作業することができ、大容量ファイルに最も効率的である可能性があります。
awk '
BEGIN { FS=OFS="|" }
{ print tolower($8 FS $9 FS $10), $0 }
' file |
sort -t'|' -k1,3 |
awk -F '|' '
{
name = $1 FS $2 FS $3
sub(/([^|]*\|){3}/,"")
}
name != prev {
if ( cnt <= 30 ) printf "%s", buf
buf = ""
cnt = 0
prev = name
}
{
buf = buf $0 ORS
cnt++
}
END { if ( cnt <= 30 ) printf "%s", buf }
'
最後のスクリプトは入力順序を保持しません。必要に応じて、元の行番号の追加のソートキーを追加して、最終的に元の順序で並べ替えることができます。
上記はすべてawkで動作し、GNU awkではより簡単に実装できますが、IMHOの場合、移植性を失う価値はありません。