首先引用另一个文件的脚本

uni*_*ipe 3 networking linux script bash awk

嗨,我有一个脚本,在其中我需要从脚本生成的 IP 中获取主机名。该脚本会将这些 IP 生成为 1 个只有 1 列的整洁文件。它实际上只是 IP 地址(每行 1 个)。我有另一个名为“db”的文件,如下所示:

IP Hostname
Run Code Online (Sandbox Code Playgroud)

'db' 是我的数据库,用于存储委派给这些 IP 的 IP 地址和主机名列表。这些是静态地址,不会改变,通常是服务器或交换机等。我需要的是脚本生成的 IP 地址,我想用这个数据库文件中的主机名 FIRST 解析它们,如果没有在那里找到它,然后运行host命令。我已经在做后者,host但我真的希望它们首先来自我的 db 文件。最终输出只需要 1 个文件和 1 列主机名。我有一些使用 awk 和数组的想法,但似乎无法完全得到我需要的东西。

G-M*_*ca' 6

grep是主要目的是在文本中查找模式(或模式)的命令。它对这项任务的简单应用是

grep 1.2.3.4 db
Run Code Online (Sandbox Code Playgroud)

这将输出“ IP_address Hostname”从线路(或多个)db匹配的图案文件“ 1.2.3.4”。请注意,我说的是line (s)(而不是line)并匹配模式 (而不是包含 string),因为这里有几个问题。

  • 一个是grep,正如我所说的,(默认情况下)搜索模式而不是字符串。这些模式被称为正则表达式,并且有大量关于它们的文档。本次讨论中关于正则表达式的最重要的事实是句点“ .”是匹配任何单个字符的模式。因此,例如,模式( regex )1.2.3.4 将匹配字符串 132.3641a2b3c4。就IP_address列而言,这些可能不是问题,但此类字符串可能会出现在Hostname列中。
  • 另一个是,除非另有说明,否则会 在行的任何位置grep搜索提供的模式。所以模式将匹配包含和的行。1.2.3.431.2.3.41.2.3.42

但我相信你会很好地得到你想要的行 - 并且只有那行 - 使用命令

grep "^1.2.3.4[[:space:]]" db
Run Code Online (Sandbox Code Playgroud)

在哪里

  • ^” 是另一个在正则表达式中很特殊的字符;这意味着该模式必须出现在一行的开头。
  • [[:space:]]”代表一个空白字符;空格或制表符。如果你确定你的db文件只使用了空格,你可以只搜索一个空格;例如,

    grep "^1.2.3.4 " db
    
    Run Code Online (Sandbox Code Playgroud)

这些仍然会找到以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.41\.2\.3\.4,而第三个则取消了“ ^”的特殊含义(因此31.2.3.4仍将匹配)。

如上所述,这些命令所有符合整个线路db该IP地址相匹配的文件。要仅获取主机名(第二列),请使用

grep "^1.2.3.4[[:space:]]" db | awk '{print $2}'
Run Code Online (Sandbox Code Playgroud)

这只会将主机名写入标准输出(通常是屏幕)。脚本中更有用的操作是

db_host=$(grep "^1.2.3.4[[:space:]]" db | awk '{print $2}')
Run Code Online (Sandbox Code Playgroud)

它将该输出捕获到 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" = "" ]
    然后
        #使用host命令查找$this_IP_address 
        主机“$this_IP_address” | 头-n 1 | awk '{打印 $5}'
    别的
        回声“$db_host”
    菲
完成 < src_ip

grep -f src_ip db对于您描述的问题(如果我理解正确的话)不会特别有用,因为它会报告db匹配任何 IP 地址的所有行src_ip - 让您找出哪些 IP 地址不匹配。


我想到了一种更简单的方法:

db_host=$(grep "^$this_IP_address[[:space:]]" db | awk '{print $2}')
if [ "$db_host" = "" ]
then
    Use the host command.
          ?
fi

它将 shell 变量复制this_IP_addressawk变量中this_one ,然后说“打印第一个字段等于 的任何行的第二个字段this_one。” 这是一个过程,而不是两个过程,它消除了“ .”匹配任意字符的问题。db_host=$(…)像以前一样把它包起来。