如何从字符串中删除点字符而不再次调用 sed 或 awk?

如何从字符串中删除点字符而不再次调用 sed 或 awk?

我有一个名为的文件hostlist.txt,其中包含如下文本:

host1.mydomain.com
host2.mydomain.com
anotherhost
www.mydomain.com
login.mydomain.com
somehost
host3.mydomain.com

我有以下小脚本:

#!/usr/local/bin/bash

while read host; do
        dig +search @ns1.mydomain.com $host ALL \
        | sed -n '/;; ANSWER SECTION:/{n;p;}';
done <hostlist.txt \
        | gawk '{print $1","$NF}' >fqdn-ip.csv

哪个输出到fqdn-ip.csv

host1.mydomain.com.,10.0.0.1
host2.mydomain.com.,10.0.0.2
anotherhost.internal.mydomain.com.,10.0.0.11
www.mydomain.com.,10.0.0.10
login.mydomain.com.,10.0.0.12
somehost.internal.mydomain.com.,10.0.0.13
host3.mydomain.com.,10.0.0.3

我的问题是如何删除.逗号之前的没有再次调用sed还是gawk?我可以在现有的sed或调用中执行一个步骤来gawk删除点吗?

hostlist.txt将包含 1000 个主机,因此我希望我的脚本快速高效。

答案1

命令sedawk命令以及删除尾随句点都可以组合成一个 awk 命令:

while read -r host; do dig +search "$host" ALL; done <hostlist.txt | awk 'f{sub(/.$/,"",$1); print $1", "$NF; f=0} /ANSWER SECTION/{f=1}'

或者,分布在多行上:

while read -r host
do
    dig +search "$host" ALL
done <hostlist.txt | awk 'f{sub(/.$/,"",$1); print $1", "$NF; f=0} /ANSWER SECTION/{f=1}'

因为awk命令跟在done语句后面,所以只awk调用一个进程。尽管效率在这里可能并不重要,但这比在每个循环中创建新的 sed 或 awk 进程更有效。

例子

有了这个测试文件:

$ cat hostlist.txt 
www.google.com
fd-fp3.wg1.b.yahoo.com

该命令产生:

$ while read -r host; do dig +search "$host" ALL; done <hostlist.txt | awk 'f{sub(/.$/,"",$1); print $1", "$NF; f=0} /ANSWER SECTION/{f=1}'
www.google.com, 216.58.193.196
fd-fp3.wg1.b.yahoo.com, 206.190.36.45

怎么运行的

awk 一次隐式读取其输入一条记录(行)。此 awk 脚本使用单个变量 ,f它表示前一行是否是答案部分标题。

  • f{sub(/.$/,"",$1); print $1", "$NF; f=0}

    如果前一行是答案部分标题,f则将为 true,并执行花括号中的命令。第一个从第一个字段中删除尾随句点。第二个打印第一个字段,然后是,,最后一个字段。第三条语句重置f为零(假)。

    换句话说,f这里起到逻辑条件的作用。f如果非零(在 awk 中表示“true”),则执行大括号中的命令。

  • /ANSWER SECTION/{f=1}

    如果当前行包含字符串ANSWER SECTION,则该变量f设置为1(true)。

    这里,/ANSWER SECTION/充当逻辑条件。如果当前值与正则表达式匹配,则其值为 true ANSWER SECTION。如果是,则执行花括号中的命令。

答案2

dig可以读入包含主机名列表的文件并一一处理它们。您还可以告诉dig抑制除答案部分之外的所有输出。

这应该会给你你想要的输出:

dig -f hostlist.txt +noall +answer +search | 
    awk '{sub(/\.$/,"",$1); print $1","$5}'

awksub()函数用于.从第一个字段末尾去除文字句点。然后awk打印字段 1 和 5,并用逗号分隔。

注意:hostlist.txt未解析的条目将被完全丢弃 - 它们不会出现在 stdout 或 stderr 上。

(在 Linux 和 FreeBSD 上测试)

答案3

将您的调用更改gawk为以下内容:

| gawk '{print substr($1,1,length($1)-1)","$NF}' >fqdn-ip.csv

相关内容