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

Lin*_*oob 12 sed awk string shell-script regular-expression

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

host1.mydomain.com
host2.mydomain.com
anotherhost
www.mydomain.com
login.mydomain.com
somehost
host3.mydomain.com
Run Code Online (Sandbox Code Playgroud)

我有以下小脚本:

#!/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
Run Code Online (Sandbox Code Playgroud)

输出到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
Run Code Online (Sandbox Code Playgroud)

我的问题是如何.调用sedgawk再次调用的情况下删除逗号之前的那个?我可以在现有的sedgawk将删除点的调用中执行的步骤吗?

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

Joh*_*024 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}'
Run Code Online (Sandbox Code Playgroud)

或者,分布在多行中:

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}'
Run Code Online (Sandbox Code Playgroud)

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

例子

有了这个测试文件:

$ cat hostlist.txt 
www.google.com
fd-fp3.wg1.b.yahoo.com
Run Code Online (Sandbox Code Playgroud)

该命令产生:

$ 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
Run Code Online (Sandbox Code Playgroud)

这个怎么运作

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

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

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

    换句话说,f此处用作逻辑条件。如果f非零(在 awk 中表示“真”),则执行花括号中的命令。

  • /ANSWER SECTION/{f=1}

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

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


cas*_*cas 7

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

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

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

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

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

(在 Linux 和 FreeBSD 上测试)


Dop*_*oti 6

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

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