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

标签 bash sed

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

例如,这用作输入数据:

@ IN SOA dnsserver. hostmaster.example.net. ( 2013112202 21600  900 691200 86400 )

但这不是:

@ 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

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

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

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

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

求助! :-)

最佳答案

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

那在 awk 中呢?

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

SOA=$(awk 'BEGIN{RS="@"} NR==2{print $6}' $SOAfile)

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

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

删除注释似乎是多余的删除文件的顶部,但可能还有其他行,如#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)

或者,分解以便于阅读:

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

这足够灵活,可以处理您可能遇到的任何行拆分,因为它计算到沿多行的 field。它还会根据您的区域段是否包含可选的“IN”关键字来调整字段编号。

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

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

看起来像是线路噪音,对吧? :-) 为便于阅读而分解,它看起来像这样:

/^@/,/^[^;]*)/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.
}

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

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

关于bash - 如何使用 sed 从文件中获取 SOA 序列号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23229339/

相关文章:

java - 字符串:用 "("替换 "\("

linux - grep 包含特殊字符的变量

php - Sed 和 PHP 关联数组

linux - 如何使用 bash 脚本计算单词中出现次数最多的 3 个字母序列

linux - Sed:添加到特定行的末尾

regex - 如何打印仅包含 BASH 列表中字符的行?

bash - 如何用 Bash 中另一个变量的值替换变量中的占位符字符或单词?

bash - Jenkins - 通过 SSH 发布 - EXEC : STDOUT/STDERR - bash: service: command not found

sed - 提取版本号子字符串

linux - 在文件中每第 n 次出现字符时插入内容