正则表达式从命令输出中打印字符串

时间:2016-09-13 23:56:55

标签: perl perl-module

我编写了一个使用正则表达式的函数,并从命令输出中打印所需的字符串。 该脚本按预期工作。但它不支持动态输出。目前,我使用正则表达式" icmp"和"确定"并打印值。现在,typedestinationreturn code可能会发生变化。命令很可能根本不返回输出。我该如何处理这种情况?

sub check_summary{

    my ($self) = @_;

    my $type  = 0;
    my $return_type = 0;

    my $ipsla = $self->{'ssh_obj'}->exec('show ip sla');

    foreach my $line( $ipsla) {
    if ( $line =~ m/(icmp)/ ) {
            $type = $1;
      }
      if ( $line =~ m/(OK)/ ) {
            $return_type = $1;
      }
    }

    INFO ($type,$return_type);
}


    command Ouptut :

    PSLAs Latest Operation Summary
    Codes: * active, ^ inactive, ~ pending

    ID           Type        Destination       Stats       Return      Last
                                               (ms)        Code        Run
    -----------------------------------------------------------------------
    *1           icmp      192.168.25.14    RTT=1       OK          1 second ago

2 个答案:

答案 0 :(得分:2)

更新进行了一些澄清 - 我们只需要最后一行

通常情况下,您不需要正则表达式来解析输出,如图所示。您有空格分隔的字段,只需split该行并选择您需要的元素。

我们被告知感兴趣的行是命令输出的最后一行。然后我们不需要循环但可以使用线条获取数组的最后一个元素。目前还不清楚$ipsla如何包含输出 - 作为多行字符串或者可能作为arrayref。由于它是命令的输出,因此我将其视为多行字符串,类似于qx返回的内容。然后,而不是foreach循环

my @lines = split '\n', $ipsla;      # if $ipsla is a multi-line string
# my @lines = @$ipsla;               # if $ipsla is an arrayref

pop @lines while $line[-1] !~ /\S/;  # remove possible empty lines at end

my ($type, $return_type) = (split ' ', $lines[-1])[1,4];

以下是对代码的一些评论。如果需要更多,请告诉我。

我们可以在显示的输出中看到直到我们需要的字段没有空格。因此,我们可以通过split ' ', $lines[-1]将空行的最后一行拆分为( ... )[1,4],然后按pop @lines取第2和第5个元素(索引1和4)。这是我们需要的两个值,我们分配它们。

如果输出以空行结束,我们首先删除它们,只要最后一行没有非空格字符while $lines[-1] !~ /\S/,就行while ( $lines[-1] !~ /\S/ ) { pop @lines } 。这与

相同
my $data_start;
foreach (@lines) 
{
    if (not $data_start) { 
        $data_start = 1 if /^\s* -+ \s*$/x;  # only dashes and optional spaces
    }
    else {
        my ($type, $return_type) = (split)[1,4];
        print "type: $type, return code: $return_type\n";
    }
}

原始版本,为澄清而编辑。它也是完成所需工作的有效方式。

我假设数据在仅有破折号的行之后开始。达到该行后设置一个标志,如果设置了标志则处理这些行。给出其余的代码,循环

void function1(Myclass class1, int myvar)
{
   // do some stuff
}

void function2(Myclass class1, int myvar)
{
   // do some other stuff
}

// ... maybe some more similar functions

这是一个草图,直到澄清到来。它还假设有多行而不是一行。

答案 1 :(得分:0)

我不确定该命令输出的所有可能性,因此我的正则表达式可能需要调整。

我假设目标是获取变量中所有列的值。我选择使用列名作为哈希键将值存储在哈希中。我打印结果用于调试/演示目的。

use strict;
use warnings;

sub check_summary {
    my ($self) = @_;

    my %results = map { ($_,undef) } qw(Code ID Type Destination Stats Return_Code Last_Run); # Put results in hash, use column names for keys, set values to undef.

    my $ipsla = $self->{ssh_obj}->exec('show ip sla');    

    foreach my $line (@$ipsla) {
        chomp $line; # Remove newlines from last field

        if($line =~ /^([*^~])([0-9]+)\s+([a-z]+)\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s+([[:alnum:]=]+)\s+([A-Z]+)\s+([^\s].*)$/) {
            $results{Code}        = $1; # Code prefixing ID
            $results{ID}          = $2;
            $results{Type}        = $3;
            $results{Destination} = $4;
            $results{Stats}       = $5;
            $results{Return_Code} = $6;
            $results{Last_Run}    = $7;
        }
    }

    # Testing
    use Data::Dumper;
    print Dumper(\%results);
}

# Demonstrate
check_summary();

# Commented for testing
#INFO ($type,$return_type);

处理提交的测试行。

编辑: 正则表达式允许您指定模式而不是您尝试匹配的确切文本。这很有力但有时很复杂。您需要阅读Perl Regular Expression文档才能真正了解它们。

Perl正则表达式还允许您捕获匹配的文本。这可以在单个模式中多次完成,这是我们能够使用一个表达式捕获所有列的方式。匹配进入编号变量......     $ 1     $ 2