如果一个文件中包含另一文件中内容的正则表达式,则删除这些行

如果一个文件中包含另一文件中内容的正则表达式,则删除这些行

我有一个包含 DNS 记录的大文件(150K+ 行),我将其称为 FileA。我有一个包含某些名称的较小文件 FileB。我想删除 FileA 中的所有行结束于FileB 中有什么。但是我愿意不是如果名称出现在记录的开头,则想要删除该行。

我知道如何手动grep -v name$删除记录末尾出现的名称,但我需要一个循环来遍历整个 FileB。到目前为止我的尝试都失败了。

这是我希望能说明我所追求的一个例子:

FileA:
hosta IN A 10.20.30.40
hostb IN A 20.30.40.50
myurl IN CNAME hostb
yours IN CNAME hostb

如果FileB包含hostb,则只删除最后两行;前两行保持原样。

答案1

您可以使用该-f标志来 grep 查找 FileB 中的所有行:

grep -v -f FileB FileA

这几乎就是你想要的。但这也删除了图案所在的FileB线条不是在最后,并且您明确指出它应该仅在最后时匹配。所以我们需要进行FileB相应的修改。我们可以使用sed, 来添加regex行尾的 ,即$符号:

sed 's/$/$/' FileB

这看起来好像没有替换任何内容,但实际上它$在行的每一端都添加了一个。

现在我们可以使用进程替换将所有这些放在一起:

grep -v -f <(sed 's/$/$/' FileB) FileA

答案2

要循环整个 FileB,您可以使用以下方法:

for i in `cat FileB`
do
<do your work>
done

但也许通过 CNAME 过滤会更好

答案3

sed可以这样做:

sed -n '/^[^ ]*$/{H;d;};G;/ \(.*\)\n.*\n\1/d;P' fileB fileA

这是:第一个进程fileB。如果这些行不包含空格,则它们应该是 fileB 中的主机名,我们将它们添加到保留空间并继续 ( {H;d;})

所有其他行都应该是 fileA 的。通过在主机名列表 ( ) 后附加保留空间G,可以删除主机名列表中重复的行的最后一个单词的所有行。打印其余行,不带尾随列表 ( P)。选项-n禁止默认输出。

编辑: 其实一个人应该做

sed -n '/^[^ ]*$/{H;d;};G;/ \(.*\)\n.*\n\1\n/d;/ \(.*\)\n.*\n\1$/d;P' fileB fileA

以避免特殊情况。

相关内容