如何删除文件中的重复出现?

时间:2013-01-22 06:43:14

标签: linux bash grep

我是bash编程的新手(grep / uniq / sort / etc ...),我在尝试从给定格式的文件中删除重复项时遇到问题

--
name: joe
tag: 123
--
name: mike
tag: 000
--
name: dave
tag: 123
--
name: loopy
tag: 123
--

基本上我想要的是删除文件中具有相同标签号的重复项,如下所示:

--
name: joe
tag: 123
--
name: mike
tag: 000
--

3 个答案:

答案 0 :(得分:5)

这个任务非常适合awk。如果你有gawk或mawk可用,你可以通过适当地设置记录分隔符来完成它:

awk -v RS='--\n' -v ORS='--\n' '!h[$4]++' infile

输出:

--
name: joe
tag: 123
--
name: mike
tag: 000
--

这通过记住已经看到哪些标签(h[$4]++),即每条记录中的第四个元素来起作用。增量前面的爆炸(!)确保条件仅在h[$4]为零时才为真,因此默认规则({ print $0 })仅在第一次看到标记时被调用

略短的版本:

awk '!h[$4]++' RS='--\n' ORS='--\n' infile

编辑 - 处理名称字段包含空格的记录

如果名称字段包含空格,则字段数会有所不同。你可以通过稍微改变字段来处理这个问题:

awk '!h[$4]++' RS='--\n' ORS='--\n' FS='\n| *: *' infile

答案 1 :(得分:1)

awk '/name/{x=$0}/tag/{a[$0]++;if(a[$0]<2){print "--\n"x,"\n",$0"\n--"}}' your_file

测试如下:

> cat temp
--
name: joe
tag: 123
--
name: mike
tag: 000
--
name: dave
tag: 123
--
name: loopy
tag: 123
--
> awk '/name/{x=$0}/tag/{a[$0]++;if(a[$0]<2){print "--\n"x,"\n",$0"\n--"}}' temp
--
name: joe 
 tag: 123
--
--
name: mike 
 tag: 000
--

/name/ {在一个变量中存储行,这样如果下一个标记不重复,我们就可以使用这个临时变量。}

/tag/ {构建一个带有行数的关联数组。不止一个会导致重复。只有在计数为1时才打印}

答案 2 :(得分:-2)

如果foobar是包含删除重复项的行的文件:

awk '{ if (arry[$3]++ == 0) print $0; }' foobar

数组中的$ 3表示仅根据第3列中的值删除重复项。如果要删除整个重复行,请改用$ 0。

使用awk这种方式的另一个好处就是不改变输入行的顺序(sort / uniq会这样做)。