【问题标题】:Perl Unable to truncate stringPerl 无法截断字符串
【发布时间】:2020-03-31 10:16:40
【问题描述】:

我正在尝试从命令“dspmq”的输出中提取 AAA 和 BBB。 $dspmq

QMNAME(AAA)                                           STATUS(Running)
QMNAME(BBB)                                           STATUS(Running)

但它不适用于以下代码。

perl -e 'use Data::Dumper qw(Dumper);my @qmgrlist = `dspmq`;$size = @qmgrlist;foreach my $i (@qmgrlist){my @temp1 = split /QMNAME\(/, $i;print @temp1;}'
AAA)                                           STATUS(Running)

BBB)                                           STATUS(Running)

我能够截断"QMNAME(",但无法截断AAABBB 右侧的那些。基本上我想得到"QMNAME(" 和直接")" 之间的字符串。请帮忙。

【问题讨论】:

  • 试试 perl -e 'map { print $1 if /QMNAME((.+?))/ } `dspmq`'

标签: string perl ibm-mq truncate


【解决方案1】:

我认为这里的正则表达式方法比split() 更好,但您可以使用split(),方法是拆分括号并获取返回列表中的第二项。

for (@qmgrlist) {
  say +(split /[()]/)[0];
}

并简要说明您使用命令行选项来运行此代码。如果您 a) 将 qspmq 的输出通过管道传输到您的代码中,并且 b) 使用 -n 一次处理一条记录,则可以使其更简单。

$ perl -nE 'say +(split /[()]/)[1]' `dspmq`

还有 -M 用于加载模块(例如 -MData::Dumper),但您似乎不再使用 Data::Dumper。

【讨论】:

    【解决方案2】:

    split 不会做你需要的。我只会使用正则表达式来匹配您需要的子字符串

    所以从这里改变循环

    foreach my $i (@qmgrlist)
    {
        my @temp1 = split /QMNAME\(/, $i;
        print @temp1;
    }
    

    到这里

    foreach my $i (@qmgrlist)
    {
        print "$1\n"
            if /QMNAME\((.+?)\)/;
    }
    

    【讨论】:

    • 正确的方法,但正则表达式比必要的更广泛,它可能会回溯很多。 / ^ QMNAME \( ( [^\)]+ ) \) /x 更好。
    • 同意正则表达式可能更广泛,但对于输入数据集来说没问题。为什么要让它变得比它需要的更复杂?
    【解决方案3】:

    试试这个 perl 单行:
    dspmq | perl -lne 'print for m{ QMNAME [(] ( [^)]* ) [)] }x'


    这里,dspmq STDOUT 使用管道 | 输入到 perl 代码的 STDIN 中,该代码具有以下标志:
    -e 告诉 Perl 解释器查找内联代码而不是单独的脚本文件。
    -n 将输入逐行提供给内联代码(这样您就不需要将输出存储在数组中 - 这对大输出很重要,而不是您的情况)。
    @987654327 @ 在将输入记录分隔符(*NIX 上的换行符)提供给代码之前将其剥离,并在 print 之后自动附加它。

    print ... for ... m{... (...) ...} 代码打印括号中捕获的每个模式。
    捕获的模式是[^)]*,这是字符类中列出的not (^) 的最大字符数(0 个或多个),即not 右括号。​​
    [(] ... [)] 是文字括号,为了便于阅读,转义为字符类。我更喜欢这样转义:\( ... \).
    QMNAME 用于明确程序员的意图:您想要括号中 QMNAME 后面的字符串。我更喜欢使用字段索引,例如 1,它可以保护您免受在不同选项、不同系统等上使用的命令输出的微小变化。
    最后,m{...}x 中的 x 正则表达式修饰符允许忽略 cmets 和空格,并且为了可读性而首选。

    相关:
    Cutting the output of a dspmq command

    【讨论】:

    • 对我们感兴趣的for
    【解决方案4】:

    可以使用以下代码实现所需的输出

    use strict;
    use warnings;
    
    use feature 'say';
    
    map{ say $1 if /QMNAME\((.+?)\)/ } <DATA>;
    
    
    __DATA__
    QMNAME(AAA)                                           STATUS(Running)
    QMNAME(BBB)                                           STATUS(Running)
    

    输出

    AAA
    BBB
    

    和一个班轮(未经测试 - 我在 Windows 电脑上)

    dspmq | perl -lne 'print $1 if /QMNAME\((.+?)\)/'

    【讨论】:

      猜你喜欢
      • 2012-02-10
      • 1970-01-01
      • 1970-01-01
      • 2014-09-14
      • 2015-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多