我正在编写一个bash脚本,我需要从多个字符串中提取IPv4和IPv6地址范围,然后根据需要对其进行格式化,然后再保存到文件中。
我的正则表达式正常工作:http://regexr.com?38jsb(未优化,粗略添加)
但是,如果我使用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范围?什么是更好的解决方案?
注意:我正在使用示例数据进行测试
答案 0 :(得分: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
以排除颜色输出。
答案 1 :(得分:2)
首先,单引号正则表达式变量赋值(regex='...'
)。
然后,使用grep -Po
(和双引号$regex
),正如@BroSlow建议的那样(注意-P
并非在所有平台上都可用(例如,OSX)) - { {1}}激活对正则表达式所需的PCRE(Perl兼容正则表达式)的支持。
把它们放在一起:
-P
替代:关注@ l' L' l示例,这里是一个大大简化的解决方案,可以处理示例数据(再次依赖于{{1 }}):
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"
OSX的变体,其中-P
不支持echo "$txt" | grep -Po '\bip[46]:\K[^ ]+'
:
grep