Linux cmdを使用して列に基づいてuniq行のみを取得する方法は?

Linux cmdを使用して列に基づいてuniq行のみを取得する方法は?

これは私のデータセットです。

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関連するすべての行が削除されます。

sortuniqLinuxまたは他の方法を使用してこの問題を解決できますか?

答え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ブロックの外側の式構文を利用します。trueawk

(1)私のコメントへの回答バッファリングされていない解決策は、ファイルの一部のデータを一時的にRAMに保存するため、引用符で囲みます。するRAM使用量が付属しています。ただし、ファイルの内容をそのまま保存するわけではありません。またRAM内の他のスクロール保持データ(ここでは実用的な意味では、「バッファリング」を考えます。)

答え2

ファイルが/tmp/dataPerlの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唯一の解決策

  1. 命令に従わない

    awk -F, 'NR>1 { count[$1]++ ; line[$1]=$0 ;} 
       END { for ( c in count) if (count[c] ==1) print line[c]}' data
    
  2. 秩序を維持

    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]印刷ライン

  • acol[]バリアントの行順序を保存する順序を保存することです。

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

関連情報