![打印所有具有重复字段的行的最有效方法是什么?](https://linux22.com/image/1594234/%E6%89%93%E5%8D%B0%E6%89%80%E6%9C%89%E5%85%B7%E6%9C%89%E9%87%8D%E5%A4%8D%E5%AD%97%E6%AE%B5%E7%9A%84%E8%A1%8C%E7%9A%84%E6%9C%80%E6%9C%89%E6%95%88%E6%96%B9%E6%B3%95%E6%98%AF%E4%BB%80%E4%B9%88%EF%BC%9F.png)
以下文件 fruit_notes.txt 有三个用竖线分隔的列:水果、颜色和品尝笔记。我想打印所有具有重复颜色字段的行。顺序并不重要。
banana|YELLOW|My turtle likes these.
cherry|RED|Sweet and tasty
grapefruit|YELLOW|Very juicy
grape|PURPLE|Yummy
lemon|YELLOW|Sour!
apple|RED|Makes great pie
orange|ORANGE|Oranges make me laugh.
这有效...
> grep -F "`awk -F"|" '{print $2}' fruit_notes.txt | sort | uniq -d`" fruit_notes.txt
banana|YELLOW|My turtle likes these
cherry|RED|Sweet and tasty
grapefruit|YELLOW|Very juicy
lemon|YELLOW|Sour!
apple|RED|Makes great pie
然而,这似乎是一个尴尬的(没有双关语的意思)解决方案。它读取文件两次:一次是在颜色字段中查找重复项,另一次是查找与重复颜色匹配的行。它也容易出错。例如,以下行将被错误地打印:
jalapeños|GREEN|My face turns RED when I eat these!
有没有更好的方法来做到这一点,也许单独使用 awk?
答案1
这会改变输出的顺序,但只需要读取文件一次:
$ awk -F'|' '$2 in a{if(a[$2])print a[$2];a[$2]=""; print; next} {a[$2]=$0}' fruit_notes.txt
banana|YELLOW|My turtle likes these.
grapefruit|YELLOW|Very juicy
lemon|YELLOW|Sour!
cherry|RED|Sweet and tasty
apple|RED|Makes great pie
怎么运行的:
$2 in a{if(a[$2])print a[$2];a[$2]=""; print; next}
如果
$2
是关联数组中的键a
,则(a)如果a[$2]
不为空,则打印它,(b)设置a[$2]
为空,(c)打印当前行,(d)跳过其余命令并从下一行重新开始。a[$2]=$0
如果这是我们第一次遇到
$2
,请将当前行保存在a
键下$2
。