如何在文本文件中查找重复行,而某些行可能被注释掉或开头有不同的标记?

如何在文本文件中查找重复行,而某些行可能被注释掉或开头有不同的标记?

我有一个文本文件,其中的行是这样混合的:

###  Comments

# Comments
86.242.200.81 banana.domain.net          # comment
86.242.200.3 orange.domain.net
31.28.225.81 monkey.anotherdomain.net

51.18.33.4 puffin.domainz.com
#31.28.220.80 monkey.anotherdomain.net   # comment
86.242.201.3 orange.domain.net

如何找到重复的host.domain?

在这种情况下,有两个: monkey.anotherdomain.netorange.domain.net

考虑到这一点..

  • 条目后的尾随注释需要被忽略,因为它们可能不在重复项上。
  • 如果该行被注释掉,仍然应该找到重复的行。
  • 应忽略 IP 地址的差异。

答案1

这很有趣。

首先,我们需要消除尾随评论,如:

86.242.200.81 banana.domain.net          # comment

我们可以使用以下命令来做到这一点(假设只有空格,没有制表符):

sed 's/  *#.*//'

如果您的主机文件中有选项卡,可以先运行以下命令:

tr '\t' ' '

然后我们需要消除“注释掉这一行”注释,我将其定义为 IP 地址前面的单个哈希字符。我们可以像这样删除它们:

sed '/^#[0-9]/ s/^#//'

将以上内容放在一起可以得到:

###  Comments

# Comments
86.242.200.81 banana.domain.net
86.242.200.3 orange.domain.net
31.28.225.81 monkey.anotherdomain.net

51.18.33.4 puffin.domainz.com
31.28.220.80 monkey.anotherdomain.net
86.242.201.3 orange.domain.net

如果我们对第二列 ( sort -k2) 进行排序,我们会得到一个按名称排序的列表:

86.242.200.81 banana.domain.net
# Comments
###  Comments
31.28.220.80 monkey.anotherdomain.net
31.28.225.81 monkey.anotherdomain.net
86.242.200.3 orange.domain.net
86.242.201.3 orange.domain.net
51.18.33.4 puffin.domainz.com

现在,如果我们告诉忽略第一个字段,我们可以申请uniq查找重复项:uniq

uniq -c -f 1

这给了我们:

  2 
  1 86.242.200.81 banana.domain.net
  1 # Comments
  1 ###  Comments
  2 31.28.220.80 monkey.anotherdomain.net
  2 86.242.200.3 orange.domain.net
  1 51.18.33.4 puffin.domainz.com

因此,如果我们查找计数为 2 或更高的行,我们就找到了重复项。把这些放在一起我们得到:

#!/bin/sh

tr '\t' ' ' |
sed '
    /^#[0-9]/ s/^#//
    s/  *#.*//
    /^ *$/ d
' |
sort -k2 |
uniq -f 1 -c |
awk '$1 > 1 {print}'

上述脚本中的最后一条语句查找(field1)awk中的计数为 的行。uniq> 1

运行上面的脚本看起来像

答案2

如果实际的像您在数据开头描述的那样的注释行存在并且将被忽略,如果没有某种关于如何区分重要注释行的假设,我不知道如何满足第2点要忽略的注释行。我假设重要的注释行在第二个字段中包含句点。

awk 'NF && $2 ~ /[.]/{++a[$2]}; 
 END{for (k in a) if(a[k] > 1) print k}' file
orange.domain.net
monkey.anotherdomain.net

答案3

sed 's/\(.\)#.*/\1/' file | cut -f 2 -d\ | sort | uniq -d
  • 删除前面有任何内容的注释sed 's/\(.\)#.*/\1/'
  • 仅过滤第二列cut -f 2 -d\
  • 对行进行排序以便进行以下比较sort
  • 并且只打印副本uniq -d

请注意,除非有可能有像这样的行

86.242.200.81 banana.domain.net#comment

您可以将上面的内容简化为:

cut -f 2 -d\  file | sort | uniq -d

因为评论将被视为第三个字段。

答案4

那么短、简单、直的方法怎么样呢?

awk '/#*\d/{print $2}' file | sort | uniq -d

这允许报告 host.domain 重复项,即使它们被井号 (#) 注释掉。

相关内容