1

我正在尝试解析具有这种模式的字符串

src [interface_name:source_address[/source_port]] 

其中括号中的部分是可选的。所以有3种可能的变体

src
src LAN:10.115.1.204
src LAN:10.115.1.204/8080

我想从这个字符串中捕获接口源 ip源端口。

我的第三个变体的正则表达式是

($srcinterface,$srcip,$src_port) = m/^src (.*?):(.*?)\/(.*?)/;

但我不知道如何制作适用于所有 3 个变体的正则表达式。

编辑 问题的更大部分是像 src dst 信息也从系统接收,我需要重复正则表达式。请参阅下面的字符串:-

src dst outside:125.22.32.192
src outside:182.201.183.178 dst outside:125.22.32.192
src outside:182.201.183.178/5525 dst outside:125.22.32.192/8595
4

4 回答 4

1

改用这个:

/^src(?> (\w++):((?>[0-9]{1,3}\.){3}[0-9]{1,3})(?>\/([0-9]++))?)?/

一个示例脚本:

#!/usr/bin/perl

use strict;

my $str = "src
src LAN:10.115.1.204
src LAN:10.115.1.204/8080";
my $i = 0;
while($str =~ /^src(?> (\w++):((?>[0-9]{1,3}\.){3}[0-9]{1,3})(?>\/([0-9]++))?)?/gm) {
print "\n[match " . ++$i . "]"
    . "\nWhole match    : $&"
    . "\nCapture group 1: $1"
    . "\nCapture group 2: $2"
    . "\nCapture group 3: $3\n";
}

对于更宽松的模式,您可以使用:

/^src(?> (\w++):([^\/\n]++)(?>\/([^\n]++))?)?/gm

或这个:

/^src(?> (\w++):([^\/\n]++)(?>\/(\S++))?)?/gm

这些模式的想法是使用否定字符类,例如[^\/\n]表示所有不是斜杠或换行符的字符。您可以轻松地调整这些类以满足您添加或删除字符的需要。

于 2013-07-19T09:29:19.853 回答
1

我不是 Perl 大师,但也许这行得通:

($srcinterface,$srcip,$src_port) = m/^src\s*(?:(.*?):(.*?)(?:\/(.*?))?)?/;

?:应该使它成为一个隐藏组,?在组的末尾使其成为可选的。

好吧,可读性变得混乱......

于 2013-07-19T09:29:58.833 回答
1

目前尚不清楚哪些字段是可选的,但您可以简单地在正则表达式上拆分以分隔那里的内容。

在这个程序中,@fields数组将包含指定的字段数。假设可选字段从右侧消失(即没有接口名称就没有源地址,没有名称和地址就没有源端口),您可以简单地计算这些字段@fields以查看提供了哪些字段。

use strict;
use warnings;

use Data::Dump;

for (
    'src',
    'src LAN:10.115.1.204',
    'src LAN:10.115.1.204/8080') {

    my @fields = split /[\/\s]+/;

    dd \@fields;
}

输出

["src"]
["src", "LAN:10.115.1.204"]
["src", "LAN:10.115.1.204", 8080]
于 2013-07-19T09:39:09.397 回答
1

这个正则表达式对我有用

($srcinterface, $srcip, $src_port) = m@^src (?:([^:]+):([^/]+))?(?(1)(?:/(.+))?)@;

笔记:

  • 我正在使用否定字符类(例如[^:]),并且+由于下面的正则表达式定义不明确(简单地说,将匹配零长度字符串) ,这.*?会给变体 2 和 3 带来麻烦。.*?.*?

  • 我将interface_name:source_address部分设为可选,并带有一个封闭(?:...)?

  • 然后我使用了条件正则表达式(?(1)pattern),意思是“pattern如果捕获组 1 匹配成功则匹配”

    实际上,如果interface_name:source_address匹配,则查找/port

  • 由于/port是可选的,我将部分包装在另一个条件正则表达式中(?:...)?

对于它的价值,我认为Borodin 的基于拆分的答案简单,而Casimir et Hippolyte 的基于正则表达式的答案在稳健性方面更好,因为它实际上验证了每个组件。我只是为了完成而发布这个。

于 2013-07-19T11:00:43.417 回答