1

我是 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
--
4

3 回答 3

5

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

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

输出:

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

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

稍短的版本:

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

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

如果名称字段有空格,则字段计数会有所不同。您可以通过稍微不同的字段拆分来处理此问题:

awk '!h[$4]++' RS='--\n' ORS='--\n' FS='\n| *: *' infile
于 2013-01-22T08:42:53.437 回答
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 时才打印}

于 2013-01-22T06:58:52.057 回答
-2

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

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

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

以这种方式使用 awk 具有不改变输入行的顺序(sort/uniq 所做的)的额外优势。

于 2013-01-22T08:21:06.573 回答