我有一个这样的.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,但它不工作。


当前回答

如果你想使用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 -u -t, -k1,1 file

-u表示唯一 -t,逗号是分隔符 -k1,1表示键字段1

测试结果:

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

通过先使用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

要考虑多列。

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

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

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

如果你想保留最后一份副本,你可以使用

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

这是我的要求

在这里

Tac将逐行反转文件

好吧,这比用awk隔离列更简单,如果你需要删除给定文件中具有特定值的所有内容,为什么不直接使用grep -v:

例如,删除所有值为“col2”的内容 线:col1、col2 col3 col4

grep -v ',col2,' file > file_minus_offending_lines

如果这还不够好,因为有些行可能会因为匹配的值显示在不同的列中而被不恰当地剥离,你可以这样做:

Awk来隔离问题列: 如。

awk -F, '{print $2 "|" $line}'

-F设置以“,”分隔的字段,$2表示第2列,后面跟着一些自定义分隔符,然后是整行。然后你可以通过删除以违规值开头的行进行过滤:

 awk -F, '{print $2 "|" $line}' | grep -v ^BAD_VALUE

然后去掉分隔符前的内容:

awk -F, '{print $2 "|" $line}' | grep -v ^BAD_VALUE | sed 's/.*|//g'

(注意- sed命令很草率,因为它不包括转义值。同样,sed模式应该是“[^|]+”(即任何不是分隔符的东西)。希望这已经足够清楚了。