我将多个域的 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 脚本?
请帮忙!:-)
我不会为此使用 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 记录。