[英]How can I parse runmqsc command output using Perl?
我正在嘗試設計Perl regex來解析來自IBM的runmqsc實用程序的命令輸出。
感興趣的每行輸出包含一個或多個屬性/值對,格式為:“ATTRIBUTE(VALUE)”。 屬性的值可以為空,也可以包含括號本身。 通常,給定行上最多出現兩個屬性/值對,因此正則表達式是在此假設下編寫的。
Perl RE的示例輸入:
CHANNEL(TO.IPTWX01) CHLTYPE(CLUSRCVR)
DISCINT(6000) SHORTRTY(10)
TRPTYPE(TCP) DESCR( )
LONGTMR(1200) SCYEXIT( )
CONNAME(NODE(1414)) MREXIT( )
MREXIT( ) CONNAME2(SOME(1416))
TPNAME( ) BATCHSZ(50)
MCANAME( ) MODENAME( )
ALTTIME(00.41.56) SSLPEER()
CONTRIVED() ATTR (00-41-56)
CONTRIVED() DOCTORED()
MSGEXIT( )
我有以下Perl代碼來捕獲每個屬性/值對。
my $resplit = qr/\s+([^\s]+(?:\([^)]*\))?)\s?/;
while ( <IN2> )
{ s/[\s\r\n]+$//;
if ( m/^\s(?:$resplit)(?:$resplit)?$/ )
{ my ($one,$two) = ($1,$2);
print "one: $one, two: $two\n";
}
}
以上代碼應用於示例輸入時的輸出:
one: CHANNEL(TO.IPTWX01), two: CHLTYPE(CLUSRCVR) one: DISCINT(6000), two: SHORTRTY(10) one: TRPTYPE(TCP), two: DESCR( ) one: LONGTMR(1200), two: SCYEXIT( ) one: CONNAME(NODE(1414)), two: MREXIT( ) one: MREXIT( ), two: CONNAME2(SOME(1416)) one: TPNAME( ), two: BATCHSZ(50) one: MCANAME( ), two: MODENAME( ) one: ALTTIME(00.41.56), two: SSLPEER() one: CONTRIVED(), two: ATTR(00-41-56) one: CONTRIVED(), two: DOCTORED() one: MSGEXIT(, two: )
除了上面輸出中的最后一行之外,這種方法很有用。 我真的很難弄清楚如何修改上面的表達式$ resplit來捕獲最后一種情況。
任何人都可以提供有關如何使這項工作或其他方法的任何想法/建議?
Text :: Balanced模塊旨在處理此類問題。 這種方法也可以處理任意數量的列。
use strict;
use warnings;
use Text::Balanced qw(extract_bracketed);
my ($extracted, $remainder, $prefix);
while ( defined($remainder = <DATA>) ){
while ( Get_paren_text() ){
$prefix =~ s/ //g;
print $prefix, $extracted, "\n";
}
}
sub Get_paren_text {
($extracted, $remainder, $prefix)
= extract_bracketed($remainder, '()', '[\w ]+');
return defined $extracted;
}
__DATA__
CHANNEL(TO.IPTWX01) CHLTYPE(CLUSRCVR) FOO( ( BAR) )
DISCINT(6000) SHORTRTY(10) BIZZ((((BUZZ) ) ) ) )
TRPTYPE(TCP) DESCR( )
LONGTMR(1200) SCYEXIT( )
CONNAME(NODE(1414)) MREXIT( )
MREXIT( ) CONNAME2(SOME(1416))
TPNAME( ) BATCHSZ(50)
MCANAME( ) MODENAME( )
ALTTIME(00.41.56) SSLPEER()
CONTRIVED() ATTR (00-41-56)
CONTRIVED() DOCTORED()
MSGEXIT( )
我想嘗試使用Regexp::Grammars
。
所以這里是:
#! /opt/perl/bin/perl
use strict;
#use warnings;
use 5.10.1;
use Regexp::Grammars;
my $grammar = qr{
<line>
<token: line>
(?: <[pair]> \s* )+
(?{
my $arr = $MATCH{pair};
local $MATCH = {};
for my $pair( @$arr ){
my($key) = keys %$pair;
my($value) = values %$pair;
$MATCH->{$key} = $value;
}
})
<token: pair>
<attrib> \s* \( \s* <value> \s* \)
(?{
$MATCH = {
$MATCH{attrib} => $MATCH{value}
};
})
<token: attrib>
[^()]*?
<token: value>
(?:
<MATCH=pair> |
[^()]*?
)
}x;
use warnings;
my %attr;
while( my $line = <> ){
$line =~ /$grammar/;
for my $key ( keys %{ $/{line} } ){
$attr{$key} = $/{line}{$key};
}
}
use YAML;
say Dump \%attr;
--- ALTTIME: 00.41.56 ATTR: 00-41-56 BATCHSZ: 50 CHANNEL: TO.IPTWX01 CHLTYPE: CLUSRCVR CONNAME: NODE: 1414 CONNAME2: SOME: 1416 CONTRIVED: '' DESCR: '' DISCINT: 6000 DOCTORED: '' LONGTMR: 1200 MCANAME: '' MODENAME: '' MREXIT: '' MSGEXIT: '' SCYEXIT: '' SHORTRTY: 10 SSLPEER: '' TPNAME: '' TRPTYPE: TCP
while ( <IN2> ) {
while ( /([A-Z]+)\s*(\((?:[^()]*+|(?2))*\))/g ) {
print "$1$2\n";
}
}
這適用於嵌套的parens,例如
CONNAME(NODE(1414, SOME(1416) ) ) ATTR (00-41-56)
(?2)部分是遞歸的,* +表示“不回溯” - 僅適用於Perl 5.10或更高版本; 我從http://faq.perl.org/perlfaq6.html#Can_I_use_Perl_regul得到了這個
#!/usr/bin/perl
use strict;
use warnings;
my @parsed;
while ( my $line = <DATA> ) {
while ( $line =~ / ([A-Z0-9]+) \s* \( (.*?) \) \s /gx ) {
push @parsed, { $1 => $2 }
}
}
use Data::Dumper;
print Dumper \@parsed;
__DATA__
CHANNEL(TO.IPTWX01) CHLTYPE(CLUSRCVR)
DISCINT(6000) SHORTRTY(10)
TRPTYPE(TCP) DESCR( )
LONGTMR(1200) SCYEXIT( )
CONNAME(NODE(1414)) MREXIT( )
MREXIT( ) CONNAME2(SOME(1416))
TPNAME( ) BATCHSZ(50)
MCANAME( ) MODENAME( )
ALTTIME(00.41.56) SSLPEER()
CONTRIVED() ATTR (00-41-56)
CONTRIVED() DOCTORED()
MSGEXIT( )
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.