我有一个包含 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
以避免特殊情况。