嗨,我有一个脚本,我需要从脚本生成的 IP 中获取主机名。该脚本会将这些 IP 生成到 1 个整洁的文件中,其中只有 1 列。它实际上只是 IP 地址(每行 1 个)。我还有另一个名为“db”的文件,如下所示:
IP Hostname
“db” 是我的数据库,用于存储 IP 地址和委托给这些 IP 的主机名列表。这些是静态地址,不会改变,通常是服务器或交换机等。我需要的是脚本生成的 IP 地址,我想首先用这个数据库文件中的主机名解析它们,如果在那里找不到,则运行命令host
。我已经在做后者,host
但我真的希望它们首先来自我的 db 文件。最终输出只需要 1 个文件和 1 列主机名。我对使用 awk 和数组有一些想法,但似乎无法完全得到我需要的东西。
答案1
grep
是主要目的是在文本中查找模式(或模式)的命令。它最简单的应用是
grep 1.2.3.4 db
这将输出文件中与模式“ ”匹配的“ IP_address Hostname
”行。请注意,我说的是db
1.2.3.4
线(編號)(而不是线) 和匹配模式
(而不是包含字符串),因为这里有几个陷阱。
- 一个是
grep
,正如我所说,(默认情况下)搜索模式而不是字符串.这些模式被称为常用表达,并且有大量关于它们的文档。对于本次讨论,关于正则表达式最重要的事实是句点“.
”是与任何单个字符匹配的模式。因此,例如,图案(正则表达式)1.2.3.4
将匹配字符串132.364
和1a2b3c4
。这些可能不是问题,就IP_address
列,但此类字符串可能出现在Hostname
柱子。 - 另一个是,除非另有说明,否则
grep
搜索提供的模式线上的任何地方. 因此该模式1.2.3.4
将匹配包含31.2.3.4
和 的行1.2.3.42
。
但我相信你会很好地得到你想要的那行——而且只有那行——用命令
grep "^1.2.3.4[[:space:]]" db
在哪里
- “
^
” 是正则表达式中的另一个特殊字符;它表示该模式必须出现在行的开头。 “
[[:space:]]
” 表示空白字符;空格或制表符。如果你确定你的db
文件只使用空格,你可以直接搜索空格;例如,grep "^1.2.3.4 " db
这些仍会找到以132.364
或开头的行1a2b3c4
。但是,如果您的db
文件结构正确,则文件中的行开头不应该有这样的字符串db
。
您可以.
使用以下任一项来阻止“ ”匹配任意字符:
grep "^1\.2\.3\.4[[:space:]]" db
grep "^1\.2\.3\.4 " db
grep -F "1.2.3.4 " db
但是前两个方法需要您在脚本中进行许多繁琐的转换1.2.3.4
,1\.2\.3\.4
而第三个方法则会去掉“ ^
”的特殊含义(因此31.2.3.4
仍然匹配)。
如上所述,这些命令都匹配整个线从db
与 IP 地址匹配的文件中获取主机名。要仅获取主机名(第二列),请使用
grep "^1.2.3.4[[:space:]]" db | awk '{print $2}'
这只会将主机名写入标准输出(通常是屏幕)。脚本中更有用的操作是
db_host=$(grep "^1.2.3.4[[:space:]]" db | awk '{print $2}')
它将输出捕获到 shell 变量中db_host
。
因此,最后,脚本的这一部分可能看起来像
db_host=$(grep "^$this_IP_address[[:space:]]" db | awk '{print $2}') 如果 [ “$db_host” = “” ] 然后 使用主持人命令。 ︙ 菲
将其放入循环中,其中变量this_IP_address
将接受要处理的每个 IP 地址。如果您将它们放在文件中(即其他文件,与 分开db
,然后一次一行地读取该文件。
例如,如果你在名为的文件中有一个 IP 地址(每行一个)src_ip
,而你只想将主机名写入标准输出,那么你可以这样写:
读取 this_IP_address 时 做 db_host=$(grep "^$this_IP_address[[:space:]]" db | awk '{print $2}') 如果 [ “$db_host” = “” ] 然后 #使用主持人查找命令$此IP地址。 主机“$this_IP_address”| head -n 1 | awk'{print $5}' 别的 回显“$db_host” 菲 完成< src_ip
grep -f src_ip db
db
对于您所描述的问题来说并不是特别有用(如果我理解正确的话),因为它会报告与任何 IP 地址匹配的所有行src_ip
- 让您弄清楚哪些 IP 地址不匹配。
我想到了一个更简单的方法:
awk -v this_one="$this_IP_address" '$1 == this_one {print $2}' db
它将 shell 变量复制this_IP_address
到awk
变量中this_one
,然后说“打印任何行中第一个字段等于的第二个字段this_one
”。这是一个过程,而不是两个过程,它消除了“ .
”匹配任意字符的问题。像以前一样将其包装起来db_host=$(…)
。