これは私のデータセットです。
col1,col2,col3
a,b,c
a,d,f
d,u,v
f,g,h
d,u,g
x,t,k
予想出力:
f,g,h
x,t,k
選択基準:
何かが複数回発生すると、col1
関連するすべての行が削除されます。
sort
uniq
Linuxまたは他の方法を使用してこの問題を解決できますか?
答え1
これは「バッファされていません」(1) 2段階の方法ですawk
(通常のファイルのみ)。
awk -F',' 'NR==FNR{cnt[$1]++;next} FNR>1&&cnt[$1]==1' input.csv input.csv
これはファイルを2回処理するため、コマンドラインでパラメータとして2回宣言します。
- このパラメータは
-F','
フィールド区切り文字をに設定します,
。 - 最初のステップでは、
NR
グローバル行カウンターがFNR
ファイルごとの行カウンターと等しい場合、列 1 の各値が配列で見つかった頻度を記録しますcnt
(その値を「配列索引」として使用)、すぐに処理に移動します.次の行。 - 2番目のパスでは、最初の列の現在値の発生カウンタが正確に1であるかどうか、ファイルの行番号が1より大きいかどうかを確認します(ヘッダーをスキップする)。これが真の場合のみ、現在の行が印刷されます。これは、現在行を印刷するように指示するルール
awk
ブロックの外側の式構文を利用します。true
awk
(1)私のコメントへの回答バッファリングされていない解決策は、ファイルの一部のデータを一時的にRAMに保存するため、引用符で囲みます。するRAM使用量が付属しています。ただし、ファイルの内容をそのまま保存するわけではありません。またRAM内の他のスクロール保持データ(ここでは私実用的な意味では、「バッファリング」を考えます。)
答え2
ファイルが/tmp/data
Perlの1行で実行できる操作であるとします。
perl -e 'while(<STDIN>) { /(^\S+?),/; $show->{$1}=$_; $count->{$1}++;}; foreach(keys %$show) {print $show->{$_} if($count->{$_} == 1);}' < /tmp/data
またはもっと読みやすくするには:
while(<STDIN>) { #loop through all lines in the input and put the lines in "$_"
/(^\S+?),/; #Everything before the first "," now ends up in "$1"
$show->{$1} = $_; #a hash will be created with as keys the "$1" and as values the "$_"
$count->{$1}++; #In the hash $count the number of occurrences will be increased everytime the same $1 appears
}
foreach(keys %$show) { #loop trough all lines
print $show->{$_} if($count->{$_} == 1); #only print them if they occur once
}
答え3
awk
唯一の解決策
命令に従わない
awk -F, 'NR>1 { count[$1]++ ; line[$1]=$0 ;} END { for ( c in count) if (count[c] ==1) print line[c]}' data
秩序を維持
awk -F, 'NR>1 { row[a]=$0; col[a]=$1; count[$1]++; ++a; } END { for (i=0; i<a; ++i) if (count[col[i]]==1) print row[i]; }' data
どこ
-F,
,
awkに区切り文字として使用するように指示するNR>1
最初の行以降count[$1]++
最初の列の要素数の計算line[$1]=$0
店舗ラインEND
ファイル終了後for ( c in count)
要素の繰り返しif (count[c] ==1)
一つしかないならprint line[c]
印刷ラインa
col[]
バリアントの行順序を保存する順序を保存することです。
1行だけです。読みやすさのために折りました。
答え4
必須のPOSIXツールのすべてのバージョンを使用し、入力内のすべての文字を装飾/並べ替え/使用/装飾解除します(入力が実際にカンマおよび/または改行を含む可能性のある引用フィールドを含むCSVでない限り、他のすべての回答も失敗します)出力の入力行の順序を維持し、入力を一度だけ開きます。したがって、入力がパイプまたはファイルから出て、入力全体をメモリに保存しない場合に機能します。
$ awk 'BEGIN{FS=OFS=","} NR>1{print ++cnt[$1], NR, $0}' file |
sort -nt, -k1,1r -k2,2 |
awk -F, '(!seen[$3]++) && ($1==1)' |
cut -d, -f3-
f,g,h
x,t,k