如何在不再次调用sed或awk的情况下从字符串中删除点字符?


12

我有一个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

我的问题是如何删除.逗号前的内容而不进行调用sedgawk再次调用?我可以在现有步骤中执行某些步骤,sed还是gawk可以删除点的调用?

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


2
有什么原因dig +short对您不起作用?
罗杰·利普斯科姆2016年

@RogerLipscombe,因为hostlist.txt中的某些主机只是主机名,而不是FQDN,因此我使用+ search来解析它们。
Linoob

Answers:


18

sed命令,该awk命令以及尾随时间的删除都可以组合为一个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为零(false)。

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

  • /ANSWER SECTION/{f=1}

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

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


谢谢@ John1024!我不知道awk不必在循环内(我认为只有在最后一行时它才在最后一行起作用)。是f任意变量还是f{}awk功能的显式部分?
Linoob

别客气。 f是一个任意变量。您实际上可以将{}复杂的逻辑条件放在前面。 f这只是一个非常简单的逻辑条件:如果非零,则为true,如果为零,则为false。
John1024 '16

@Linoob请注意,在第二个命令中,/ANSWER SECTION/起逻辑条件的作用,类似于f在第一个命令中起的作用。我已经更新了答案来讨论这个问题。
John1024 '16

7

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上测试)


6

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

| gawk '{print substr($1,1,length($1)-1)","$NF}' >fqdn-ip.csv
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.