2014-03-24 93 views
0

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

我已经得到了正则表达式做工精细:http://regexr.com?38jsb(不优化,大致增加)

然而,在bash它抛出,如果我有egrep其中规定egrep: repetition-operator operand invalid

这里是我的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范围?什么是更好的解决方案?

注:我用样本数据进行测试的目的,我

+3

未经检验的,但相当肯定'egrep'不会与一个数字,你正在使用运营商/类的工作(例如'\ D')。尝试用'grep -Po'切换到Perl风格的正则表达式。你也应该引用'“$ regex”'。 – BroSlow

+0

不,那没用!还有其他建议吗?感谢您发布btw! –

+0

你在使用GNU grep吗? – BroSlow

回答

2

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

然后,使用grep -Po(和双引号$regex),作为@BroSlow建议(注意-P并不适用于所有平台(例如,OSX)) - -P激活用于PCREs(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'升的例子,这里有一个大大简化的解决方案,与样本数据(再次依靠-P)的作品:

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

变了OSX,其中grep不发upport -P

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

现在,如果只有OS X grep有'-Po'选项,这些类型的事情会容易得多:) –

+2

@ l'l l:同意;我已经添加了简化解决方案的OSX变体。 – mklement0

+0

@ 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到如果需要,排除彩色输出。

+0

感谢您的解决方案,我不得不使用@ mklement0解决方案,因为它更简单。 P.S虽然赞成。 –