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

par*_*oid 5 text-processing uniq

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

###  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
Run Code Online (Sandbox Code Playgroud)

如何找到 host.domain 重复项?

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

考虑到..

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

lar*_*sks 6

这是一个有趣的。

首先,我们需要消除尾随注释,例如:

86.242.200.81 banana.domain.net          # comment
Run Code Online (Sandbox Code Playgroud)

我们可以通过以下方式做到这一点(假设只有空格,没有制表符):

sed 's/  *#.*//'
Run Code Online (Sandbox Code Playgroud)

如果您的主机文件中有选项卡,请先运行:

tr '\t' ' '
Run Code Online (Sandbox Code Playgroud)

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

sed '/^#[0-9]/ s/^#//'
Run Code Online (Sandbox Code Playgroud)

把上面的放在一起得到我们:

###  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
Run Code Online (Sandbox Code Playgroud)

如果我们对第二列 ( 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
Run Code Online (Sandbox Code Playgroud)

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

uniq -c -f 1
Run Code Online (Sandbox Code Playgroud)

这给了我们:

  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
Run Code Online (Sandbox Code Playgroud)

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

#!/bin/sh

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

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

运行上面的脚本看起来像这样