需要在两个空行之间提取一段文本

时间:2013-09-30 06:46:33

标签: bash shell sed dns

我一直在缓慢而稳定地开发一个bash脚本,可以快速获取有关域的一些基本DNS信息。 (想想像LeafDNS或IntoDNS,但我可以快速从CLI运行。)今天,一位同事给了我完成脚本所需的最后一块,这是如何获取域指向的域名服务器(及其IP)如域名注册商vís-a-vísdig +trace +additional所报告的那样。

然而,问题是dig +trace +additional返回了许多我既不想要也不需要的额外信息。返回的四个文本块(用空行分隔)中,我只需要第三个(前两个是根名称服务器,TLD的父名称服务器,第四个块是DNS区域中报告的名称服务器)。理想情况下,我还想省略dig附加到第三个文本块末尾的注释,只有名称服务器及其IP。

我确实找到this作为解决方案,通过sed输出挖掘,但我只是模糊地熟悉sed。当我直接使用sep命令copypasta时,我得到了第一个和第三个块。以下是输出的示例:

calyodelphi@dragonpad:~ $ dig +trace +additional dragon-architect.com | sed '/^$/,/^$/!d'

; <<>> DiG 9.7.3-P3 <<>> +trace +additional dragon-architect.com
;; global options: +cmd
.           214851  IN  NS  m.root-servers.net.
.           214851  IN  NS  a.root-servers.net.
.           214851  IN  NS  b.root-servers.net.
.           214851  IN  NS  g.root-servers.net.
.           214851  IN  NS  j.root-servers.net.
.           214851  IN  NS  d.root-servers.net.
.           214851  IN  NS  e.root-servers.net.
.           214851  IN  NS  f.root-servers.net.
.           214851  IN  NS  l.root-servers.net.
.           214851  IN  NS  c.root-servers.net.
.           214851  IN  NS  k.root-servers.net.
.           214851  IN  NS  h.root-servers.net.
.           214851  IN  NS  i.root-servers.net.
;; Received 228 bytes from 192.168.16.1#53(192.168.16.1) in 18 ms


dragon-architect.com.   172800  IN  NS  ns1.dragon-architect.com.
dragon-architect.com.   172800  IN  NS  ns2.dragon-architect.com.
ns1.dragon-architect.com. 172800 IN A   70.84.243.130
ns2.dragon-architect.com. 172800 IN A   70.84.243.131
;; Received 106 bytes from 192.33.14.30#53(b.gtld-servers.net) in 165 ms


calyodelphi@dragonpad:~ $ 

我现在几乎迷失了,非常感谢帮助。如果它简单,优雅,高度便携,易于阅读,并附带有关sed命令如何工作的解释,那么我可以从中学到它。我也愿意使用grep或awk;以最便携和可维护的结果为准。

编辑: 我知道几个挖掘参数(特别是+ nocomments和+ nostats)。不幸的是,他们不能使用+ trace。因此,我必须使用sed或awk手动删除统计信息/评论。

编辑2: 此外,直到今天我还没有想到解决方案需要考虑像.co.uk或.com.au这样的顶级域名。我在bbc.co.uk和melbourneit.com.au这样的几个域上运行了dig +trace +additional,看看这是否改变了输出,但事实并非如此。仍然返回了四个输出块,这意味着两个提供的解决方案仍然可以完全按预期工作。

2 个答案:

答案 0 :(得分:1)

通过将记录选择器设置为\n\n,将其分为4个块,然后打印块3。 PS这可能只适用于支持RS中多个字符的gawk和其他awk。

dig +trace +additional dragon-architect.com | awk 'NR==3' RS="\n\n"
dragon-architect.com.   172800  IN      NS      ns1.dragon-architect.com.
dragon-architect.com.   172800  IN      NS      ns2.dragon-architect.com.
ns1.dragon-architect.com. 172800 IN     A       70.84.243.130
ns2.dragon-architect.com. 172800 IN     A       70.84.243.131
;; Received 106 bytes from 192.12.94.30#53(192.12.94.30) in 60 ms

您甚至可以删除单引号。但最好将它们留在那里。

awk NR==3 RS="\n\n"

答案 1 :(得分:0)

您可以尝试使用。将RS设置为空字符串以将空白行中的寄存器拆分,并将FS设置为换行符以将每个寄存器的字段与该字符分开。这样我必须选择第三个(FNR == 3),删除最后一个字段($NF)和尾随空格,然后打印:

dig +trace +additional dragon-architect.com | awk '
   BEGIN { RS = ""; FS = OFS = "\n" } 
   FNR == 3 { $NF = ""; sub( /[[:space:]]+$/, "" ); print }
'

它产生:

dragon-architect.com.   172800  IN  NS  ns1.dragon-architect.com.
dragon-architect.com.   172800  IN  NS  ns2.dragon-architect.com.
ns1.dragon-architect.com. 172800 IN A   70.84.243.130
ns2.dragon-architect.com. 172800 IN A   70.84.243.131