web-dev-qa-db-ja.com

列ごとに「uniq」する方法はありますか?

次のような.csvファイルがあります。

[email protected],2009-11-27 01:05:47.893000000,example.net,127.0.0.1
[email protected],2009-11-27 00:58:29.793000000,example.net,255.255.255.0
[email protected],2009-11-27 00:58:29.646465785,example.net,256.255.255.0
...

ファイルから重複した電子メール(行全体)を削除する必要があります(つまり、上記の例で[email protected]を含む行の1つ)。 __カンマで区切られたフィールド1のみでuniqを使用するにはどうすればよいですか? manによると、uniqには列のオプションがありません。

sort | uniqで試しましたが、うまくいきません。

167
Eno
sort -u -t, -k1,1 file
  • 固有の場合は-u
  • -t,ですので、コンマが区切り文字です
  • キーフィールド1の-k1,1

テスト結果:

[email protected],2009-11-27 00:58:29.793000000,xx3.net,255.255.255.0 
[email protected],2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1 
286
Carl Smotricz
awk -F"," '!_[$1]++' file
  • -Fはフィールド区切り文字を設定します。
  • $1は最初のフィールドです。
  • _[val]は、ハッシュ_(通常の変数)でvalを検索します。
  • ++インクリメントし、古い値を返します。
  • !は論理否定を返します。
  • 最後に暗黙の印刷があります。
86
ghostdog74

複数の列を検討します。

列1および列3に基づいて一意のリストを並べ替えて指定します。

sort -u -t : -k 1,1 -k 3,3 test.txt
  • -t :コロンはセパレータです
  • 列1および列3に基づく-k 1,1 -k 3,3
14
Prakash

または、uniqを使用する場合:

<mycvs.cvs tr -s ',' ' ' | awk '{print $3" "$2" "$1}' | uniq -c -f2

与える:

1 01:05:47.893000000 2009-11-27 [email protected]
2 00:58:29.793000000 2009-11-27 [email protected]
1
9
Carsten C.

複製の最後の1つを保持する場合は、使用できます

 tac a.csv | sort -u -t, -r -k1,1 |tac

私の要件でした

ここに

tacは、ファイルを1行ずつ逆順にします

4
Sumukh

これは非常に気の利いた方法です。

最初に、一意性を比較する列が固定幅になるようにコンテンツをフォーマットします。これを行う1つの方法は、フィールド/列幅指定子( "%15s")を指定してawk printfを使用することです。

これで、uniqの-fおよび-wオプションを使用して、前のフィールド/列をスキップし、比較幅(列幅)を指定できます。

以下に3つの例を示します。

最初の例では...

1)対象の列を一時的にフィールドの最大幅以上の固定幅にします。

2)-f uniqオプションを使用して前の列をスキップし、-w uniqオプションを使用して幅をtmp_fixed_widthに制限します。

3)列の末尾のスペースを削除して、その幅を「復元」します(事前に末尾のスペースがないと仮定します)。

printf "%s" "$str" \
| awk '{ tmp_fixed_width=15; uniq_col=8; w=tmp_fixed_width-length($uniq_col); for (i=0;i<w;i++) { $uniq_col=$uniq_col" "}; printf "%s\n", $0 }' \
| uniq -f 7 -w 15 \
| awk '{ uniq_col=8; gsub(/ */, "", $uniq_col); printf "%s\n", $0 }'

2番目の例では...

新しいuniq列を作成します1. uniqフィルターが適用された後、それを削除します。

printf "%s" "$str" \
| awk '{ uniq_col_1=4; printf "%15s %s\n", uniq_col_1, $0 }' \
| uniq -f 0 -w 15 \
| awk '{ $1=""; gsub(/^ */, "", $0); printf "%s\n", $0 }'

3番目の例は2番目の例と同じですが、複数の列があります。

printf "%s" "$str" \
| awk '{ uniq_col_1=4; uniq_col_2=8; printf "%5s %15s %s\n", uniq_col_1, uniq_col_2, $0 }' \
| uniq -f 0 -w 5 \
| uniq -f 1 -w 15 \
| awk '{ $1=$2=""; gsub(/^ */, "", $0); printf "%s\n", $0 }'
0
NOYB