Bash 将管道结果与输入对齐(此处为“ip”和whois grep结果)
我需要对包含IP地址的文件执行whois查找,并将国家代码和IP地址输出到新文件中。到目前为止,在我的命令中,我找到了IP地址并获得了一个与允许范围不匹配的唯一副本。然后我运行whois查找来找出谁是外国地址。最后,它将国家代码提取出来。这很好用,但我不能让它在国家代码旁边显示IP,因为whois输出中不包括IP 在输出中包含IP地址的最佳方式是什么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
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