我是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
--
答案 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会这样做)。