これが私のデータセットです:
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
Linuxまたはuniq
他の何かを使用して解決できますか?
答え1
ここでは、「非バッファリング」(1) 2 パス アプローチを示しますawk
(通常のファイルでのみ機能します)。
awk -F',' 'NR==FNR{cnt[$1]++;next} FNR>1&&cnt[$1]==1' input.csv input.csv
これにより、ファイルは 2 回処理されるため、コマンドラインで引数として 2 回指定されます。
- 引数は
-F','
フィールド区切り文字を設定します,
。 - 最初のパスでは、グローバル行カウンタ がファイルごとの行カウンタ
NR
に等しい場合、列 1 の各値が配列内で何回出現するかを登録します(配列は値を「配列インデックス」として受け取ります)。ただし、処理はすぐに次の行にスキップします。FNR
cnt
- 2 番目のパスでは、最初の列の現在の値の発生カウンタがちょうど 1 であり、ファイル内の行番号が 1 より大きいかどうか (ヘッダーをスキップするため) を確認します。これが true の場合のみ、現在の行が印刷されます。これは、
awk
ルール ブロックの外側の式が現在の行を印刷するように指示する構文true
を使用しますawk
。
(1)私が投稿したコメントに対する反応として非バッファリング引用符で囲むのは、ソリューションがファイルの一部のデータを一時的にRAMに保存するため、するRAMの使用量が伴います。ただし、ファイルの内容をそのまま保存するわけではありません。加えてRAM内の他のスクロールキーピングデータ(私実際の意味での「バッファリング」を検討します。
答え2
ファイルがあると仮定すると、/tmp/data
Perl ワンライナーで実行できます。
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