【问题标题】:While loop output multiple value comparison and echo message if differentWhile循环输出多值比较,如果不同则回显消息
【发布时间】:2016-12-27 07:11:12
【问题描述】:

我有一个循环设置来输入一个包含 IP 列表的文件。循环将使用 IP 搜索文件以获取关联的 MAC 地址。有时,每个 IP 都会列出多个 MAC。它可以是一个,也可以是七个或更多。这真是一个未知数。我所知道的是,我需要能够比较每个 IP 报告了多少 MAC,并在它们不完全匹配时回显某些内容。这是我的脚本输出现在的样子:

Testing 192.168.17.25
00:0f:XX:41:e7:50; 00:0f:XX:41:e7:50; 00:0f:XX:41:e7:50; 
Testing 192.168.17.26
00:0f:XX:43:7a:f0; 00:0f:XX:43:7a:f0; 00:0f:XX:43:7a:f0; 00:0f:XX:43:7a:f0;

这是我的while循环:

cat $list | while read line;

do
echo "Testing $line"
var=$(/bin/grep -A 10 -w $line $file | /bin/grep 'ethernet' | /bin/awk '{print  $3}')
echo $var

done

如何构造一个 if/then 进入循环以比较 MAC 地址并在找到不同的 MAC 地址时回显一条消息?

更新:$list 文件是一个带有 IP 的简单文本文件。

192.168.17.1

192.168.17.2

等等……

我通过运行 IP 来获取 MAC 的 $file 是 DHCP 租用文件。

lease 192.168.17.28 {
starts 2 2016/07/12 07:36:15;
ends 3 2016/07/13 07:36:15;
tstp 3 2016/07/13 07:36:15;
tsfp 3 2016/07/13 19:36:15;
atsfp 3 2016/07/13 19:36:15;
cltt 2 2016/07/12 07:36:15;
binding state free;
hardware ethernet 84:7b:eb:24:87:ef;
uid "\001\204{\353$\207\357";

更新:@pakistanprogrammerclub

当我运行脚本时,我得到:

[root@localhost]# ./genipmacs.sh < leasesfile > ipmaclist
awk: cmd. line:2: {ipmac[$1][$2]=1}
awk: cmd. line:2:           ^ syntax error
awk: cmd. line:6:     for(mac in ipmac[ip])
awk: cmd. line:6:                     ^ syntax error

不确定它在这里想要什么。其他东西需要用引号括起来吗?

更新 #2 @pakistanprogrammerclub

使用修改后的 awk 代码后,脚本按预期运行,没有错误。但是,我的 ipmaclist 文件如下所示:

 192.168.17.25 1       00:0
 00:0    4164    192.168.17.26
 192.168.17.27    1       192.168.17.28
 00:0    4164    192.168.17.29   192.168.17.30

由于某种原因,它没有获得 MAC。我想我只需要调整代码中的 grep 和 sed 命令。这似乎是根本原因。在脚本之外运行这些会产生您在上面看到的数据,然后 awk 会尝试解析它。 Grep 和 sed 外部脚本:

x.x.x.x x.x.x.x.  00:0
x.x.x.x.    00:0
x.x.x.x.  48:
x.x.x.x x.x.x.x  48:
x.x.x.x.   00:0

似乎只是切断了 mac 的写入线。

更新 #3

新的 ipmaclist 内容:

00:0f:94:43:fd:d0       2       x.x.x.x
x.x.x.x.   1       dc:37:14:82:a2:82
x.x.x.x.  1       00:0f:94:41:d4:d0
x.x.x.x 1       00:0f:94:41:9f:e0

租赁文件 -

x.x.x.x
x.x.x.x
x.x.x.x
x.x.x.x

更新 4

新代码也可以工作,但以相反的方式工作。

00:0f:94:c1:31:20       1       192.168.17.26
00:0f:94:c1:1f:30       3       192.168.17.27   192.168.17.28  192.168.17.29
00:0f:94:66:84:f0       1       192.168.17.30

【问题讨论】:

  • 您能否发布一个原始文件格式的示例?
  • 是的,给我一些。刚刚更新。
  • 为什么不将var 设为索引数组 并在/bin/awk '{print $3}' 之后添加| sort -u,例如var=( $(your stuff | sort -u) ) 然后${#var[@]} 告诉你有多少个独特的mac,echo "${var[@]}" 列出它们或者你可以做for i in ${var[@]}; do echo "$i"; done
  • 这就是我最终做的事情。我保持一切不变,除了我将 sort -u 添加到我的 var 变量的末尾。现在我知道如果我看到多个 MAC,我有一个重复的 IP。 .
  • 您在问题中显示的错误来自awk,告诉您它不知道[...][...] 的含义。 awk 中的多维数组与[..., ...] 一起使用。另外,您没有向我们展示那部分代码。

标签: bash if-statement while-loop


【解决方案1】:

与其手动遍历它们,不如考虑使用sort -u 删除重复项,然后使用wc -l 进行计数。

unique_mac_addrs() {
     # First, split them up to individual lines, stripping out
     # any stray spaces or blank lines, then sort and count.
     echo "$@" | tr \; $'\n' | awk '$1{print $1}' | sort -u | wc -l
}
sample1="00:0f:XX:43:7a:f0; 00:0f:XX:43:7a:f0; 00:0f:XX:43:7a:f0; 00:0f:XX:43:7a:f0;"
sample2="00:0f:XX:43:7a:f0; FF:0f:XX:43:7a:f0; EE:0f:XX:43:7a:f0; 00:0f:XX:43:7a:f0;"
unique_mac_addrs $sample1  # => 1
unique_mac_addrs $sample2  # => 3

【讨论】:

  • 你能不能详细解释一下,因为你失去了我。循环是我获取 MAC 的方式,在您的示例中,我没有看到引用的文件。
  • 这是为了你已经拥有的东西而不是用 bash 编写的内部循环。换句话说,一旦你的问题生成行中的代码看起来像我的sample 行,你就可以使用我的函数将它们后处理成结果。
【解决方案2】:

这种方法使用 gawk 4.0 生成一个制表符分隔的 MACS 列表,并从租用文件中为每个 IP 计数 - 称之为 ipmacslist:

10.0.1.1        1       00:11:22:33:44:55
10.0.1.2        2       00:11:22:33:44:56       00:11:22:37:44:56
10.0.1.3        1       00:11:22:33:44:57

您可以 grep ipmacslist 获取 $list 中的 IP 列表,然后过滤计数:

grep -F -f$list ipmacslist|awk '$2 > 1'

这是生成 ipmacslist 的代码 - 这是一个管道 - 将其放入脚本中,例如 genipmacs.sh 并在标准输入上提供租约文件内容 - ./genipmacs.sh &lt;leasefile.leases &gt;ipmacslist

# grep ip and mac from lease file
grep -Po '^lease \K[0-9.]*|hardware ethernet \K[0-9:a-f]*'|
# join pairs of consecutive lines to get ip-mac pair on one line
sed -n 'N; s/\n/\t/;p'|
# collect unique ip-mac pairs - output ip unique macs list and count
# uses gawk 4.0 2D arrays
awk '
# bail on invalid input
!/^[0-9.]+\t[0-9:a-f]+/ {
  printf("error line %d not IP-MAC pair: \"%s\"\n", NR, $0)
  exitstatus=1
  exit exitstatus
}
{ipmac[$1][$2]=1}
END {
  if(exitstatus) exit exitstatus
  for(ip in ipmac) {
    printf("%s\t%d", ip, length(ipmac[ip]))
    for(mac in ipmac[ip])
      printf("\t%s", mac)
    printf("\n")
  }
}
'

【讨论】:

  • 我没有在代码中看到任何告诉它在哪里可以找到我的租约文件的内容?在你的 grep 命令中,$list 变量是什么?
  • $list 是您自己的变量,其中包含要检查的 IP 列表的文件 - 代码是一个管道 - 向它提供标准输入上的租约文件内容 - 您可以修改它以读取其他文件中的租约文件方式也是
  • 好的。我在运行脚本时遇到了一些错误。我会更新我的帖子以添加错误。
  • 我不确定我的 awk 版本是否支持您的 awk 代码。我在 GNU Awk 3.1.7 上。如果需要,您能否修改您的答案以反映 awk 代码在 GNU Awk 3.1.7 中获得相同结果的样子?
  • 发布了新的解决方案 - 希望它适用于您的版本
【解决方案3】:

gawk 4.0 之前的解决方案使用假二维数组 - 这很痛苦 - 请升级到 gawk 4.0 - 它已经有几年历史了 -

# grep ip and mac from lease file
grep -Po '^lease \K[0-9.]*|hardware ethernet \K[0-9:a-f]*'|
# join pairs of consecutive lines to get ip-mac pair on one line
sed -n 'N; s/\n/\t/;p'|
# collect unique ip-mac pairs - output ip unique macs list and count
awk '
# bail on invalid input
!/^[0-9.]+\t[0-9:a-f]+/ {
  printf("error line %d not IP-MAC pair: \"%s\"\n", NR, $0)
  exitstatus=1
  exit exitstatus
}
{
  if(($1, $2) in ipmac) next
  if($1 in macs) {
    macs[$1]=macs[$1] "\t" $2
  } else {
    ips[i++]=$1
    macs[$1]=$2
  }
  ++nmacs[$1]
  ipmac[$1, $2]=1
}
END {
  if(exitstatus) exit exitstatus
  for(i=0; i < length(ips); ++i) {
    ip=ips[i]
    printf("%s\t%d", ip, nmacs[ip])
    printf("\t%s\n", macs[ip])
  }
}
'

它的输出和一个测试租约文件如下

10.0.1.1        1       00:11:22:33:44:55
10.0.1.2        2       00:11:22:33:44:56       00:11:22:37:4f:56
10.0.1.3        2       00:11:22:33:44:57       00:11:22:a3:44:57

测试租约文件

lease 10.0.1.1 {
  starts 5 2015/05/15 01:57:17;
  ends 5 2015/05/15 02:07:17;
  tstp 5 2015/05/15 02:07:17;
  cltt 5 2015/05/15 01:57:17;
  binding state free;
  hardware ethernet 00:11:22:33:44:55;
  client-hostname "host1";
  uid "foo";
}
lease 10.0.1.2 {
  starts 5 2015/05/15 02:09:16;
  ends 5 2015/05/15 02:19:16;
  tstp 5 2015/05/15 02:19:16;
  cltt 5 2015/05/15 02:09:16;
  binding state free;
  hardware ethernet 00:11:22:33:44:56;
  client-hostname "host2";
  uid "bar";
}
lease 10.0.1.3 {
  starts 5 2015/05/15 02:16:01;
  ends 5 2015/05/15 02:26:01;
  tstp 5 2015/05/15 02:26:01;
  cltt 5 2015/05/15 02:16:01;
  binding state free;
  hardware ethernet 00:11:22:33:44:57;
  client-hostname "host3";
  uid "baz-1";
}
lease 10.0.1.3 {
  starts 5 2015/05/15 02:17:01;
  ends 5 2015/05/15 02:27:01;
  tstp 5 2015/05/15 02:27:01;
  cltt 5 2015/05/15 02:17:01;
  binding state free;
  hardware ethernet 00:11:22:a3:44:57;
  client-hostname "host3";
  uid "baz-2";
}
lease 10.0.1.2 {
  starts 5 2015/05/15 02:09:16;
  ends 5 2015/05/15 02:19:16;
  tstp 5 2015/05/15 02:19:16;
  cltt 5 2015/05/15 02:09:16;
  binding state free;
  hardware ethernet 00:11:22:37:4f:56;
  client-hostname "host2";
  uid "bar-1";
}

【讨论】:

  • 为 MAC 模式添加了十六进制数字
  • 是的。做到了。但是,现在当我运行 grep 命令时 - grep -F -f$list ipmacslist|awk '$2 > 1'。它退出并且什么也不返回。我的实际命令如下所示 - grep -F -f leases ipmaclist|awk '$2 > 1' - 其中“leases”是 IP 地址列表。该文件数据排列在单列中,只有 IP。
  • ipmaclist 的内容应该看起来像您在原始答案中显示的格式吗?因为我的没有。我会更新我的帖子。
  • 你能从 ipmaclist 和租约文件中发布几行吗?
  • 我刚刚用您要求的信息更新了我的帖子。
猜你喜欢
  • 2015-05-19
  • 2015-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多