如何使用 sed 从文件中获取 SOA 序列号?

Gra*_*ham 2 bash sed

我将多个域的 SOA 数据存储在一个$INCLUDE由区域文件获取的文件中。我编写了一个小的 sed 脚本,该脚本应该获取序列号,递增它,然后重新保存 SOA 文件。只要 SOA 文件格式正确(整个记录在一行上),一切都可以正常工作,但一旦记录被分割成多行,一切就会失败。

例如,这作为输入数据:

@ IN SOA dnsserver. hostmaster.example.net. ( 2013112202 21600  900 691200 86400 )
Run Code Online (Sandbox Code Playgroud)

但这并不:

@ IN SOA dnsserver. hostmaster.example.net. (
                            2013112202      ; Serial number
                            21600           ; Refresh every day, 86400 is 1 day
                            900             ; Retry refresh every 15 min
                            691200          ; Expire every 8 days
                            86400 )         ; Minimum TTL 1 day
Run Code Online (Sandbox Code Playgroud)

喜欢评论,我想把事情传播出去。但我需要我的脚本能够找到序列号,以便我可以增加它并重写文件。

在单行上工作的 SED 是这样的:

SOA=$(sed 's/.*@.*SOA[^0-9]*//;s/[^0-9].*//' $SOAfile)
Run Code Online (Sandbox Code Playgroud)

但对于多线......我有点迷失了。我知道我可以使用 加入线路N,但我怎么知道我是否要这样做?我是否需要根据对原始文件所做的其他分析来编写单独的 sed 脚本?

请帮忙!:-)

gho*_*oti 5

我不会为此使用 sed。虽然你可能能够暴力破解某些东西,但这需要大量的注意力才能完成,而且它看起来像线路噪声,因此之后几乎无法维护。

在 awk 中这个怎么样?

最简单的方法可能是根据@字符分割记录,如下所示:

SOA=$(awk 'BEGIN{RS="@"} NR==2{print $6}' $SOAfile)
Run Code Online (Sandbox Code Playgroud)

@但是,如果您在未注释行之前包含注释,或者在 和@序列号之间有任何注释,则会中断。你可以制作一个管道来避免这些问题......

SOA=$(sed 's/;.*//;/^@/p;1,/^@/d' $SOAfile | awk 'BEGIN{RS="@"} NR==2{print $6}')
Run Code Online (Sandbox Code Playgroud)

删除注释并删除文件顶部似乎是多余的,但可能还有其他行#include(尽管不太可能)包含您的记录分隔符。

或者你可以在纯 awk 中做这样的事情:

SOA=$(awk -v field=6 '/^@/ { if($2=="IN"){field++} for(i=1;i<field;i++){if(i==NF){field=field-NF;getline;i=1}} print $field}' $SOAfile)
Run Code Online (Sandbox Code Playgroud)

或者,为了更容易阅读而细分:

awk -v field=6 '
  /^@/ {
    if ($2=="IN") {field++;}
    for (i=1;i<field;i++) {
      if(i==NF) {field=field-NF;getline;i=1;}
    }
    print $field; }' $SOAfile
Run Code Online (Sandbox Code Playgroud)

这足够灵活,可以处理您可能遇到的任何线路分割,因为它相当于field沿着多条线路。它还根据您的区域段是否包含可选的“IN”关键字来调整字段编号。

纯 sed 解决方案不会对字段进行计数,而是使用 后的开括号后的第一个数字字符串/^@/,如下所示:

SOA=$(sed -n '/^@/,/^[^;]*)/H;${;x;s/.*@[^(]*([^0-9]*//;s/[^0-9].*//;p;}' $SOAfile)
Run Code Online (Sandbox Code Playgroud)

看起来像是线路噪声,对吗?:-) 为了便于阅读,它看起来像这样:

/^@/,/^[^;]*)/H              # "Hold" the meaningful part of the file...
${                           # Once we reach the end...
  x                          # Copy the hold space back to the main buffer
  s/.*@[^(]*([^0-9]*//       # Remove stuff ahead of the serial
  s/[^0-9].*//               # Remove stuff after the serial
  p                          # And print.
}
Run Code Online (Sandbox Code Playgroud)

这里的想法是,从以 开头的第一行开始@,我们将文件复制到 sed 的保留空间中,然后在文件末尾进行一些替换以删除序列号之前的所有文本,然后在序列号,并打印剩余的内容。

所有这些都适用于我测试过的单行和多行区域 SOA 记录。