次のような.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
で試しましたが、うまくいきません。
sort -u -t, -k1,1 file
-u
-t,
ですので、コンマが区切り文字です-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
awk -F"," '!_[$1]++' file
-F
はフィールド区切り文字を設定します。$1
は最初のフィールドです。_[val]
は、ハッシュ_
(通常の変数)でval
を検索します。++
インクリメントし、古い値を返します。!
は論理否定を返します。複数の列を検討します。
列1および列3に基づいて一意のリストを並べ替えて指定します。
sort -u -t : -k 1,1 -k 3,3 test.txt
-t :
コロンはセパレータです-k 1,1 -k 3,3
または、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
複製の最後の1つを保持する場合は、使用できます
tac a.csv | sort -u -t, -r -k1,1 |tac
私の要件でした
ここに
tac
は、ファイルを1行ずつ逆順にします
これは非常に気の利いた方法です。
最初に、一意性を比較する列が固定幅になるようにコンテンツをフォーマットします。これを行う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 }'