从 perl 代码中的 MQ 输出问题中提取数据

Data extract from MQ output issue in perl code

我的 perl 代码有问题,我编写的代码应该从 MQ 命令 dis ql(*) all 中获取一些信息, 以下是上述命令的输出示例之一,

    AMQ8409: Display Queue details.
   QUEUE(XXX.DATATYPE.NETSTATVM)           TYPE(QLOCAL)
   ACCTQ(QMGR)                             ALTDATE(2016-08-01)
   ALTTIME(18.33.19)                       BOQNAME( )
   BOTHRESH(0)                             CLUSNL( )
   CLUSTER( )                              CLCHNAME( )
   CLWLPRTY(0)                             CLWLRANK(0)
   CLWLUSEQ(QMGR)                          CRDATE(2016-08-01)
   CRTIME(18.33.19)                        CURDEPTH(0)
   CUSTOM( )                               DEFBIND(OPEN)
   DEFPRTY(0)                              DEFPSIST(YES)
   DEFPRESP(SYNC)                          DEFREADA(NO)
   DEFSOPT(SHARED)                         DEFTYPE(PREDEFINED)
   DESCR(Queue for  XXX.DataType.netstatvm)
   DISTL(NO)                               GET(ENABLED)
   HARDENBO                                INITQ( )
   IPPROCS(1)                              MAXDEPTH(20000)
   MAXMSGL(33554432)                       MONQ(QMGR)
   MSGDLVSQ(PRIORITY)                      NOTRIGGER
   NPMCLASS(NORMAL)                        OPPROCS(0)
   PROCESS( )                              PUT(ENABLED)
   PROPCTL(COMPAT)                         QDEPTHHI(80)
   QDEPTHLO(20)                            QDPHIEV(DISABLED)
   QDPLOEV(DISABLED)                       QDPMAXEV(ENABLED)
   QSVCIEV(NONE)                           QSVCINT(999999999)
   RETINTVL(999999999)                     SCOPE(QMGR)
   SHARE                                   STATQ(QMGR)
   TRIGDATA( )                             TRIGDPTH(1)
   TRIGMPRI(0)                             TRIGTYPE(FIRST)
   USAGE(NORMAL)                        

以上输出是从 MQ 中的队列之一获取的,而不是 all 命令 运行.

中的队列

从上面,我想从QUEUECURDEPTHMAXDEPTH中提取值,如下所示:-

QUEUE(XXX.DATATYPE.NETSTATVM)
CURDEPTH(0)
MAXDEPTH(20000)

所以,我写了一个perl代码来获取QUEUECURDEPTHMAXDEPTH的值,下面是我的代码,

my $qm = XXX;

open (CHS_OUT, "echo 'dis ql(*) all'|runmqsc $qm|");

while (<CHS_OUT>) {
    if ( /QUEUE\(/ ){
        my $QueueName =~ /QUEUE/(/\S+)/g;
    }
    if ( /CURDEPTH\(/ ){
        my $CurDepth =~ s/\D//g;
        chomp $CurDepth;
        print "$CurDepth \n";
    }
    if ( /MAXDEPTH\(/ ){
        my $MaxDepth =~ s/\D//g;
        chomp $MaxDepth;
        print "$MaxDepth \n";
    }
}

输出假设如下,

XXX.DATATYPE.NETSTATVM
0
20000

但是,我在提取所有这 3 条信息时收到多个错误,其中一个错误如下,

Use of uninitialized value $MaxDepth in substitution (s///) at mq_test.pl line 26, line 7361.
Use of uninitialized value $MaxDepth in scalar chomp at mq_test.pl line 27, line 7361.
Use of uninitialized value $MaxDepth in concatenation (.) or string at mq_test.pl line 28, line 7361.

这让我很困惑,因为我已经对这段代码进行了多次更改,但仍然没有成功。

您可以使用以下正则表达式

(?:QUEUE|CURDEPTH|MAXDEPTH)\(\K[^()]+

参见a demo on regex101.com


(?:QUEUE|CURDEPTH|MAXDEPTH) # one of the alternatives
\(                          # an opening bracket
\K                          # "forget" everything
[^()]+                      # not (), at least once


Perl 中,这将是:

my @matches = $str =~ /(?:QUEUE|CURDEPTH|MAXDEPTH)\(\K[^()]+/g;
print "@matches\n";
# XXX.DATATYPE.NETSTATVM
# 0
# 20000

=~ 是绑定运算符。它将左侧的字符串绑定到右侧的匹配项。但是你在 LHS 上有 my $variable - 所以字符串是空的。你想要的是匹配隐式变量,并可能存储匹配的一部分。这是通过列表上下文中的正常分配完成的:

#!/usr/bin/perl
use warnings;
use strict;

while (<>) {
    if ( /QUEUE\(/ ) {
        my ($QueueName) = /QUEUE\((\S+)\)/;
        print "QN: $QueueName\n";
    }
    if ( /CURDEPTH\(/ ) {
        my ($CurDepth) = /CURDEPTH\((\d+)/;
        print "CD: $CurDepth\n";
    }
    if ( /MAXDEPTH\(/ ) {
        my ($MaxDepth) = /MAXDEPTH\((\d+)/;
        print "MD: $MaxDepth\n";
    }
}

您也可以将所有正则表达式合并为一个,并使用哈希来存储由括号前的单词键入的值:

#!/usr/bin/perl
use warnings;
use strict;

my %info;
while (<>) {
    if (my ($key, $value)
        = / ( QUEUE | CURDEPTH | MAXDEPTH ) \( ( [^)]+ ) /x
    ) {
        $info{$key} = $value;
    }
}

for my $key (keys %info) {
    print "$key: $info{$key}\n";
}

我使用下面的命令来做一些与 awk 类似的事情:

echo "DIS QL(*) CURDEPTH MAXDEPTH"|runmqsc $qm | grep -o '^\w\+:\|\w\+[(][^)]\+[)]' | awk -F '[()]' -v OFS='\n' 'function printValues() { if ("QUEUE" in p) { print p["QUEUE"], p["CURDEPTH"], p["MAXDEPTH"], "" } } /^\w+:/ { printValues(); delete p; next } { p[] =  } END { printValues() }'

输出将如下所示:

XXX.DATATYPE.NETSTATVM
0
20000

YYY.DATATYPE.NETSTATVM
50
10000