我有一个这样的.csv文件:

stack2@domain.example,2009-11-27 01:05:47.893000000,domain.example,127.0.0.1
overflow@domain2.example,2009-11-27 00:58:29.793000000,domain2.example,255.255.255.0
overflow@domain2.example,2009-11-27 00:58:29.646465785,domain2.example,256.255.255.0
...

我必须从文件中删除重复的电子邮件(整行)(即上面示例中包含overflow@domain2.example的行之一)。如何在字段1上使用uniq(以逗号分隔)?根据man的说法,uniq没有列的选项。

我尝试了一些排序| uniq,但它不工作。


当前回答

awk -F"," '!_[$1]++' file

-F设置字段分隔符。 $1是第一个字段。 _[val]在哈希值_(一个规则变量)中查找val。 ++ increment,返回旧值。 ! 返回逻辑不。 在结尾有一个隐含的印刷。

其他回答

如果你想使用uniq:

< mycvs。cvs tr - s ',' ' ' | awk的{打印3美元”“2”“1美元}”| uniq - c - f2

给:

1 01:05:47.893000000 2009-11-27 tack2@domain.example
2 00:58:29.793000000 2009-11-27 overflow@domain2.example
1

通过先使用sort对文件排序,然后可以应用uniq。

它似乎对文件进行了很好的排序:

$ cat test.csv
overflow@domain2.example,2009-11-27 00:58:29.793000000,xx3.net,255.255.255.0
stack2@domain.example,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
overflow@domain2.example,2009-11-27 00:58:29.646465785,2x3.net,256.255.255.0
stack2@domain.example,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack3@domain.example,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack4@domain.example,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack2@domain.example,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1

$ sort test.csv
overflow@domain2.example,2009-11-27 00:58:29.646465785,2x3.net,256.255.255.0
overflow@domain2.example,2009-11-27 00:58:29.793000000,xx3.net,255.255.255.0
stack2@domain.example,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack2@domain.example,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack2@domain.example,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack3@domain.example,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack4@domain.example,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1

$ sort test.csv | uniq
overflow@domain2.example,2009-11-27 00:58:29.646465785,2x3.net,256.255.255.0
overflow@domain2.example,2009-11-27 00:58:29.793000000,xx3.net,255.255.255.0
stack2@domain.example,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack3@domain.example,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack4@domain.example,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1

你也可以做一些AWK魔术:

$ awk -F, '{ lines[$1] = $0 } END { for (l in lines) print lines[l] }' test.csv
stack2@domain.example,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack4@domain.example,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack3@domain.example,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
overflow@domain2.example,2009-11-27 00:58:29.646465785,2x3.net,256.255.255.0
awk -F"," '!_[$1]++' file

-F设置字段分隔符。 $1是第一个字段。 _[val]在哈希值_(一个规则变量)中查找val。 ++ increment,返回旧值。 ! 返回逻辑不。 在结尾有一个隐含的印刷。

要考虑多列。

根据第1列和第3列排序并给出唯一的列表:

sort -u -t : -k 1,1 -k 3,3 test.txt

-t:冒号为分隔符 -k 1,1 -k 3,3根据第1列和第3列

这里有一个非常漂亮的方法。

首先格式化内容,使要比较唯一性的列具有固定宽度。一种方法是使用带有字段/列宽度说明符(“%15s”)的awk printf。

现在uniq的-f和-w选项可以用来跳过前面的字段/列,并指定比较宽度(列的宽度)。

这里有三个例子。

在第一个例子中…

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 }'

在第二个例子中……

创建一个新的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 }'

第三个示例与第二个示例相同,但用于多个列。

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 }'