Bash 将管道结果与输入对齐(此处为“ip”和whois grep结果)

Bash 将管道结果与输入对齐(此处为“ip”和whois grep结果),bash,awk,ip-address,whois,Bash,Awk,Ip Address,Whois,我需要对包含IP地址的文件执行whois查找,并将国家代码和IP地址输出到新文件中。到目前为止,在我的命令中,我找到了IP地址并获得了一个与允许范围不匹配的唯一副本。然后我运行whois查找来找出谁是外国地址。最后,它将国家代码提取出来。这很好用,但我不能让它在国家代码旁边显示IP,因为whois输出中不包括IP 在输出中包含IP地址的最佳方式是什么 awk '{match($0,/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/); ip = substr($0,RSTART,R

我需要对包含IP地址的文件执行whois查找,并将国家代码和IP地址输出到新文件中。到目前为止,在我的命令中,我找到了IP地址并获得了一个与允许范围不匹配的唯一副本。然后我运行whois查找来找出谁是外国地址。最后,它将国家代码提取出来。这很好用,但我不能让它在国家代码旁边显示IP,因为whois输出中不包括IP

在输出中包含IP地址的最佳方式是什么

awk '{match($0,/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/); ip = substr($0,RSTART,RLENGTH); print ip}' myInputFile \
  | sort \
  | uniq \
  | grep -v '66.33\|66.128\|75.102\|216.106\|66.6' \
  | awk -F: '{ print "whois " $1 }' \
  | bash \
  | grep 'country:' \
  >> myOutputFile
我曾考虑过使用tee,但在以合理的方式排列数据时遇到了困难。输出文件应具有IP地址和国家代码。不管它们是单列还是双列

以下是一些示例输入:

12月27日04:03:30 smtpfive sendmail[14851]:tBRA3HAx014842:to=,延迟=00:00:12,延迟=00:00:01,邮件=esmtp,优先级=1681345,中继=redcondor.itctel.c 嗯。[75.102.160.236],dsn=4.3.0,stat=延期:本se超出451个收件人限制 nder 12月27日04:03:30 smtpfive sendmail[14851]:tBRA3HAx014842:to=,延迟=00:00:12,延迟=00:00:01,邮件=esmtp,优先级=1681345,中继=redcondor.itctel.c 嗯。[75.102.160.236],dsn=4.3.0,stat=延期:本se超出451个收件人限制 nder


谢谢。

一般来说:将输入作为shell变量进行迭代;然后,您可以将它们与shell的每个输出一起打印


以下内容适用于bash 4.0或更新版本(需要关联数组):


将脚本作为一个整体执行输入和输出重定向比将
>
重定向放在
printf
本身之后更有效(这将在每次打印操作之前打开文件,之后再次关闭文件,导致严重的性能损失),这就是为什么此脚本的建议调用看起来像:

countries_for_addresses </path/to/logfile >/path/to/output
地址/路径/到/输出的
countries\u

awk | sort | uniq | grep | awk | bash | grep
听起来有点过分。也许您可以提供一个示例
myInputFile
以及所需的输出,这样我们可以想出一个更好的方法。仅供参考,在
完成后放置
>任何
,比每次运行
whois
命令时都重新打开文件更有效。此外,我完全同意@fedorqui——我想不出在什么情况下,您的管道不能降到正好两个元素,而不是更多。(请记住,
awk
可以进行排序、uniq'ing和grepping——反转或其他方式)输入文件是一个sendmail日志。我似乎无法在任何地方附加文件,但下面包含了几行内容。另外,使用
awk
为bash生成命令总体上容易出现安全漏洞,因为
awk
没有任何与bash的
printf%q
相当的功能来安全地shell报价内容。这种特殊情况可能是安全的,因为用户提供的内容被限制为与IP地址匹配,但这是一个坏习惯,效果很好。现在我只需要为grep-v'66.33\| 66.128\| 75.102\| 216.106\| 66.6'添加位,我就完成了。也可以在bash中实现该逻辑<代码>案例$ip在66.33.*66.128.*75.102.*216.106.*66.6.*)继续;;esac
@user3788019,…我上面的建议实际上是一个轻触式的错误,因为它只在前缀位置匹配那些字符串,而不是排除
1.2.66.6
1.66.6.2
,尽管你也可以重写你的grep:
grep-E-v'^(66[.33 | 66[.128 | 75[.102 | 216[.106 | 66[.6])
@user3788019,如果您想知道为什么我更喜欢
[.]
而不是
\.
,请尝试查看将后者放在backticks中时会发生什么。
while read -r ip; do
  case $ip in 66.33.*|66.128.*|75.102.*|216.106.*|66.6.*) continue;; esac
  printf '%s\n' "$ip $(whois "$ip" | grep -i 'country:')"
done < <(grep -E -o '[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+' | sort -u)
countries_for_addresses </path/to/logfile >/path/to/output