【问题标题】:Regex string extraction in Perl ScriptPerl 脚本中的正则表达式字符串提取
【发布时间】:2021-12-26 18:04:15
【问题描述】:

我的 cmd 输出文本如下:

  pool: pool0
 state: ONLINE
status: Some supported features are not enabled on the pool. The pool can
        still be used, but some features are unavailable.
action: Enable all features using 'zpool upgrade'. Once this is done,
        the pool may no longer be accessible by software that does not support
        the features. See zpool-features(5) for details.
  scan: scrub repaired 0B in 01:24:15 with 0 errors on Sun Nov 14 01:48:17 2021
config:

        NAME        STATE     READ WRITE CKSUM
        pool0       ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            sda     ONLINE       0     0     0
            sdb     ONLINE       0     0     0
          mirror-1  ONLINE       0     0     0
            sdc     ONLINE       0     0     0
            sdd     ONLINE       0     0     0

errors: No known data errors

我想提取池、状态、状态、操作、扫描、配置和错误的值。 我尝试使用像 https://regexr.com/https://regex101.com/ 这样的正则表达式生成/测试端。 在那里我得到了我的匹配项和池示例的“名称”组中的值,但在 shell 中我什么也看不到

use IO::Socket::INET;
my $strCmdErg = `/sbin/zpool status`;

my $poolname=  $strCmdErg=~ /pool:\s(.*$)/gm;
print "PoolName: $poolname \n";

my $state = $strCmdErg=~ /\sstate:\s(.*$)\n/gm;
print "Status: $state \n";

输出

PoolName: 1
Status: 1

我认为“一”是匹配的指标。

谢谢!

【问题讨论】:

  • 尝试从您的正则表达式中同时删除 $\n,例如my $poolname= $strCmdErg=~ /pool:\s*(.*)/g;.
  • 提示:去掉两个匹配项上的g。它们没有意义,而且可能有害
  • use IO::Socket::INET 在您的代码示例中似乎未使用。此外,当您有另一个名为“status”的字段时,您可以为一个名为“state”的字段打印“status”。这势必会引起混乱。

标签: regex perl zfs


【解决方案1】:

这种人类可读的输出可以很容易地解析为带有split 的哈希。

use strict;
use warnings;
use Data::Dumper;

my $data = do { local $/; <DATA> };    # slurp text into variable
my %data = grep $_,                         # remove empty fields
           map { chomp; $_ }                # remove trailing newline
           split /^\s*(\w+): */m, $data;    # split the data
print Dumper \%data;

__DATA__
  pool: pool0
 state: ONLINE
status: Some supported features are not enabled on the pool. The pool can
        still be used, but some features are unavailable.
action: Enable all features using 'zpool upgrade'. Once this is done,
        the pool may no longer be accessible by software that does not support
        the features. See zpool-features(5) for details.
  scan: scrub repaired 0B in 01:24:15 with 0 errors on Sun Nov 14 01:48:17 2021
config:

        NAME        STATE     READ WRITE CKSUM
        pool0       ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            sda     ONLINE       0     0     0
            sdb     ONLINE       0     0     0
          mirror-1  ONLINE       0     0     0
            sdc     ONLINE       0     0     0
            sdd     ONLINE       0     0     0

errors: No known data errors

输出:

$VAR1 = {
          'config' => '

        NAME        STATE     READ WRITE CKSUM
        pool0       ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            sda     ONLINE       0     0     0
            sdb     ONLINE       0     0     0
          mirror-1  ONLINE       0     0     0
            sdc     ONLINE       0     0     0
            sdd     ONLINE       0     0     0',
          'status' => 'Some supported features are not enabled on the pool. The pool can
        still be used, but some features are unavailable.',
          'state' => 'ONLINE',
          'action' => 'Enable all features using \'zpool upgrade\'. Once this is done,
        the pool may no longer be accessible by software that does not support
        the features. See zpool-features(5) for details.',
          'errors' => 'No known data errors',
          'pool' => 'pool0',
          'scan' => 'scrub repaired 0B in 01:24:15 with 0 errors on Sun Nov 14 01:48:17 2021'
        };

现在您可以通过提供字段名称作为哈希键轻松打印字段。例如:

print "PoolName: $data{pool}\n";
print "State: $data{state}\n";

【讨论】:

    【解决方案2】:
    my $poolname=
    

    在标量上下文中执行正则表达式,这就是为什么你得到 1,即返回的匹配数。您需要将其更改为列出上下文,如

     my ($poolname) =
    

    为了将捕获的文本分配给变量。

    【讨论】:

      【解决方案3】:

      Perl 捕获使用变量$1$2 等:

      $strCmdErg =~ /pool:\s(.*$)/m;
      my $poolname = $1;
      print "PoolName: $poolname \n";
      

      您是正确的,您发布的代码中的 1 值是匹配的返回值,true 为 1。

      更多信息请参见https://www.perltutorial.org/regular-expression-extracting-matches/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-01-19
        • 2013-02-24
        • 1970-01-01
        • 1970-01-01
        • 2014-08-25
        • 1970-01-01
        • 2013-04-19
        • 1970-01-01
        相关资源
        最近更新 更多