【问题标题】:Extract IPv4 and IPv6 Address Ranges in Bash?在 Bash 中提取 IPv4 和 IPv6 地址范围?
【发布时间】:2014-03-25 10:33:36
【问题描述】:

我正在编写一个 bash 脚本,我需要在其中从多个字符串中提取 IPv4 和 IPv6 地址范围,然后在保存到文件之前根据要求对其进行格式化。

我的正则表达式工作正常:http://regexr.com?38jsb(未优化,粗略添加)

但是,如果我使用 egrep 声明 egrep: repetition-operator operand invalid,使用 bash 会引发错误

这是我的 bash 脚本:

#!/bin/bash

regex="(?>(?>([a-f\d]{1,4})(?>:(?1)){3}|(?!(?:.*[a-f\d](?>:|$)){})((?1)(?>:(?1)){0,6})?::(?2)?)|(?>(?>(?1)(?>:(?1)){5}:|(?!(?:.*[a-f\d]:){6,})(?3)?::(?>((?1)(?>:(?1)){0,4}):)?)?(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)(?>\.(?4)){3}))\/\d{1,2}"

echo "v=abc ip4:127.0.0.1/19 ip4:192.168.1.1/32 ip4:192.168.2.50/20 ip6:2001:4860:4000::/36 ip6:2404:6800:4000::/36 ip6:2607:f8b0:4000::/36 ip6:2800:3f0:4000::/36 ip6:2a00:1450:4000::/36 ip6:2c0f:fb50:4000::/36 ~all" | egrep -o $regex

如何在 bash 中提取这两种类型的 IP 范围?有什么更好的解决方案?

注意:我将样本数据用于测试目的

【问题讨论】:

  • 未经测试,但相当肯定egrep 不会与您正在使用的许多运算符/类一起使用(例如\d)。尝试使用 grep -Po 切换到 perl 风格的正则表达式。你也应该引用"$regex"
  • 不,那没用!还有其他建议吗?感谢您发布顺便说一句!
  • 你在使用 GNU grep 吗?
  • 我在 Mac OS X 上测试它。根据以下解决方案中的 cmets,似乎-P 在 OS X 上不起作用,这就是为什么我无法让它工作.但是我从@mklement0 那里得到了一个更好的解决方案。还是谢谢!

标签: regex bash shell


【解决方案1】:

首先,单引号正则表达式变量赋值 (regex='...')。

然后,按照@BroSlow 的建议,使用grep -Po(和双引号$regex)(注意-P 并非在所有平台(例如OSX)上都可用)---P 激活对PCRE 的支持(Perl 兼容的正则表达式),这是您的正则表达式所必需的。

把它们放在一起:

regex='(?>(?>([a-f\d]{1,4})(?>:(?1)){3}|(?!(?:.*[a-f\d](?>:|$)){})((?1)(?>:(?1)){0,6})?::(?2)?)|(?>(?>(?1)(?>:(?1)){5}:|(?!(?:.*[a-f\d]:){6,})(?3)?::(?>((?1)(?>:(?1)){0,4}):)?)?(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)(?>\.(?4)){3}))\/\d{1,2}'
txt="v=abc ip4:127.0.0.1/19 ip4:192.168.1.1/32 ip4:192.168.2.50/20 ip6:2001:4860:4000::/36 ip6:2404:6800:4000::/36 ip6:2607:f8b0:4000::/36 ip6:2800:3f0:4000::/36 ip6:2a00:1450:4000::/36 ip6:2c0f:fb50:4000::/36 ~all"
echo "$txt" | grep -Po "$regex"

替代方案:按照@l'L'l 的示例,这是一个非常简化的解决方案,适用于样本数据(再次依赖于-P):

echo "$txt" | grep -Po '\bip[46]:\K[^ ]+'

OSX 的变体,其中grep 不支持-P

echo "$txt" | egrep -o '\<ip[46]:[^ ]+' | cut -c 5-

【讨论】:

  • 现在如果只有 OS X grep 有 -Po 选项,这些类型的事情会容易得多:)
  • @l'L'l:同意;我添加了简化解决方案的 OSX 变体。
  • @mklement0 感谢您的解决方案,简化的解决方案比我的解决方案要好得多。完美:)
【解决方案2】:

此模式应与 sed 结合使用:

str="v=abc ip4:127.0.0.1/19 ip4:192.168.1.1/32 ip4:192.168.2.50/20 ip6:2001:4860:4000::/36 ip6:2404:6800:4000::/36 ip6:2607:f8b0:4000::/36 ip6:2800:3f0:4000::/36 ip6:2a00:1450:4000::/36 ip6:2c0f:fb50:4000::/36 ~all"

echo $str | grep -s -i -o "ip[0-9]\:[a-z0-9\.:/]*" --color=always | sed 's/ip[0-9]\://g'

输出:

127.0.0.1/19
192.168.1.1/32
192.168.2.50/20
2001:4860:4000::/36
2404:6800:4000::/36
2607:f8b0:4000::/36
2800:3f0:4000::/36
2a00:1450:4000::/36
2c0f:fb50:4000::/36

如果需要,可以省略 --color=always 以排除颜色输出。

【讨论】:

  • 感谢您的解决方案,我不得不使用@mklement0 解决方案,因为它更简单。 P.S 支持。
猜你喜欢
  • 2019-07-13
  • 2021-12-24
  • 1970-01-01
  • 2018-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-20
  • 2011-06-24
相关资源
最近更新 更多