如何使用Perl提取文件每行中包含的所有IPv4地址
Perl提取单行多IPv4地址的实现方法
问题场景
现有存储多类信息的文本文件,单行内容可能包含多个IPv4地址,原始文件内容示例如下:
ip_group1,1.2.3.4,otherstring1,otherstring2,4.5.6.7 ip_group2,3.4.5.6,otherstring1 ip_group3,11.21.31.41,otherstring1,otherstring2,4.5.6.7,otherstring4,1.2.3.4,otherstring5,otherstring2,41.51.16.71
原有Perl代码仅能匹配每行第一个出现的IP,会遗漏同一条记录内的其他IP,原代码如下:
use Regexp::Common qw/net/; while (<>) { print $1, "\n" if /($RE{net}{IPv4})/; }
目标输出为每行开头的分组标识+该行所有IP,用逗号分隔,预期结果如下:
ip_group1,1.2.3.4,4.5.6.7 ip_group2,3.4.5.6 ip_group3,11.21.31.41,4.5.6.7,1.2.3.4,41.51.16.71
调整方案
原代码核心问题是正则匹配未加全局匹配修饰符,默认只命中第一个结果就终止匹配。调整后的完整可运行代码如下:
use Regexp::Common qw/net/; while (<>) { chomp; # 提取每行开头的ip_group标识,仅分割1次避免后续内容含逗号导致的提取异常 my ($group_tag) = split /,/, $_, 2; # 加/g修饰符开启全局匹配,列表上下文下会返回整行所有命中的IPv4地址 my @ip_list = /($RE{net}{IPv4})/g; # 拼接分组标签和所有IP后按格式输出 print join(',', $group_tag, @ip_list) . "\n"; }
关键修改点
- 正则匹配增加
/g修饰符:默认模式下正则匹配到第一个符合规则的结果就会终止遍历,加g后会扫描整行匹配所有合规IPv4地址,配合列表上下文可以一次性拿到该行所有IP结果 - 补充分组标签提取逻辑:用
split限制分割次数为2,精准拿到每行开头的ip_groupX标识,匹配预期输出的格式要求 - 统一拼接输出:把分组标签和提取到的所有IP用逗号拼接后打印,完全对齐目标输出格式
内容的提问来源于stack exchange,提问作者Pankaj Kumar
相关产品推荐
相关产品推荐

