使用 awk 上的 system() 函数在第一列上运行命令

使用 awk 上的 system() 函数在第一列上运行命令

我运行以下代码来提取一些 IP 地址并计算它们的唯一性。例如

./my_program | awk '/^10./{a[$1 FS $2]++ } END { for(i in a) print i,a[i]}' > some_file

包含的输出some_file是这样的,即:

10.12.33.14 34
10.12.33.11 12
10.12.33.16 5

现在我想要的是运行{system("dig +short -x " i)}并将输出附加到最后一列,以便文件看起来像

10.12.33.14 34  server1.rdns.domain.tld
10.12.33.11 12  server2.rdns.domain.tld
10.12.33.16 5   server3.rdns.domain.tld

我可以一次性完成此操作,然后将输出传输到文本文件吗?

谢谢!

更新1

... END { for(i in a) cmd=sprintf("dig +short -x \"%s\"", $i); cmd | getline type; close(cmd);  printf("%s %s %s\n",i,a[i],type);

这就是输出(stderr)的结尾

dig: '.in-addr.arpa.' is not a legal name (unexpected end of input)

这是我在文件中看到的

10.12.33.14 34

更新2:

    END { for(i in a) split(i,ip," ")
    cmd=sprintf("dig +short -x \"%s\"", ip[1]); cmd | getline type; close(cmd);
    printf("%s %s %s %s\n",ip[1],ip[2],a[i],type)

答案1

您可以使用split()函数拆分 IP/端口组合并获取 IP 以供稍后在dig()命令中使用。

END { 
  for(i in a) {
    split(i, ip)
    cmd=sprintf("dig +short -x \"%s\"", ip[1])
    (cmd | getline type) > 0 ? "" : type="notResolved"
    printf("%s %s %s\n",i,a[i],type);
    close(cmd)
  }
}

我添加了一种检查命令状态的方法dig,并使用?三元运算符来更新类型的值。对于失败的情况,您可以添加自己的字符串(例如'notResolved'上面的字符串)并打印结果。

请注意,使用getline()呼入awk与使用呼叫不同system()。该类型cmd | getline var使用管道,就像cmd从 shell 运行一样,每次调用都会getline var从命令中读取一行输出。但该system()命令无法提供获取内部执行命令的输出的方法。您只能访问从内部运行的命令返回的退出代码。

PS答案部分采纳了有用的评论穆鲁。

答案2

您可以执行以下操作

步骤1:

./my_program | awk '/^10./{a[$1]++ } END { for(i in a) print i,a[i]}' | tee some_file | xargs -I{} dig +short -x {} > some_file2

第2步:

paste <(awk '{print $1}' some_file ) <(awk '{print $1}' some_file2 ) > result

如果您愿意,some_file您可以删除。some_file2rm some_file some_file2

答案3

您也可以awk完全避免使用。有点慢(尽管使用相同数量的 调用dig)但很可能更具可读性。

while read -r ip count
do
    printf "%s %s %s\n" "$ip" "$count" "$(dig +short -x "$ip" | xargs)"
done < ipaddresses.txt

相关内容