我编写了一个使用正则表达式的函数,并从命令输出中打印所需的字符串。
该脚本按预期工作。但它不支持动态输出。目前,我使用正则表达式" icmp"和"确定"并打印值。现在,type
,destination
和return 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
答案 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