【问题标题】:Split paragraphs with extra whitespace between them using Perl's paragraph mode使用 Perl 的段落模式将段落与额外的空格分开
【发布时间】:2013-07-27 06:02:53
【问题描述】:

我正在尝试解析pvdisplay(8) 的输出,它为每个物理卷打印一个单独的“段落”:

  --- Physical volume ---
  PV Name               /dev/sdb
  VG Name               vg_virtual_01
  PV Size               16.37 TiB / not usable 2.25 MiB
  Allocatable           yes 
  PE Size               4.00 MiB
  Total PE              4291533
  Free PE               3830989
  Allocated PE          460544
  PV UUID               zqi1Q6-tIag-ghQy-MmdJ-kyOS-XkmY-HpyQ51

  --- Physical volume ---
  PV Name               /dev/sda
  VG Name               vg_virtual_02
  PV Size               16.37 TiB / not usable 2.25 MiB
  Allocatable           yes 
  PE Size               4.00 MiB
  Total PE              4291533
  Free PE               1525709
  Allocated PE          2765824
  PV UUID               BlYvJW-ieVx-AjRg-p3r6-e4oC-TkPc-u2lf7x

够简单吧?

#!/usr/bin/perl

use strict;
use warnings;

my @pvs = do {
    local $/ = '';
    `pvdisplay`;
};

事实证明,并没有我想象的那么简单。由于我的数组只得到一个项目,在键盘上敲了半个小时后,我意识到段落之间的空白行实际上在 EOL 之前包含额外的空格。根据 perlvar,$/ 如果设置为空字符串,则将空行视为终止符,但需要注意的是空行不能包含任何空格或制表符。当然,$/ 是一个字符串,而不是一个正则表达式,所以我不能将它设置为 /^\s+$/ 之类的东西。

我能看到的唯一方法是首先将输出保存到一个文件中,去掉无关的空格,然后将其读回,但我不想为这么简单的东西创建一个临时文件。有没有更优雅的方法来做到这一点?

编辑:我可以使用 split(/^\s+$/m) 来做到这一点,但我只是好奇是否有办法通过更改 $/

【问题讨论】:

    标签: perl whitespace paragraph backticks


    【解决方案1】:

    嗯?只需自己拆分输出:

    my @pvs = split /\n\s*\n/, scalar `pvdisplay`;
    

    不,没有办法使用$/,除非确切的分隔符是已知的字符(如果有两个空格,你可以尝试例如$/ = "\n \n")。不要试图不必要地让你的工作更难。

    【讨论】:

    • 当我的问题引起“嗯?”时,哈哈一定会喜欢它。确凿的迹象表明我想多了。我刚刚了解了$/,正如他们所说,当你只有$/ 时,一切都开始看起来像一个段落。或者类似的东西......
    • 另外,+1 用于展示如何在不先将反引号输出写入一次性变量的情况下进行拆分。
    • 实际上,scalar 是不必要的:split 的第二个参数无论如何都在标量上下文中。但这让发生了什么事情变得更清楚了
    【解决方案2】:
    #!/usr/bin/env perl
    
    use strict;
    use warnings;
    
    local $/ = '--- Physical volume ---';
    
    while (my $chunk = <DATA>) {
        chomp $chunk;
        $chunk =~ s/\A \s+ //x;
        $chunk =~ s/\s+ \z //x;
        next unless $chunk =~ /\S/;
        my %obs = ($chunk =~  /^ (.+?[eED]) \s{2,} (\S .+)  $/gxm);
        use YAML;
        print Dump \%obs;
    }
    
    
    
    __DATA__
    --- Physical volume ---
    PV Name               /dev/sdb
    VG Name               vg_virtual_01
    PV Size               16.37 TiB / not usable 2.25 MiB
    Allocatable           yes
    PE Size               4.00 MiB
    Total PE              4291533
    Free PE               3830989
    Allocated PE          460544
    PV UUID               zqi1Q6-tIag-ghQy-MmdJ-kyOS-XkmY-HpyQ51
    
    --- Physical volume ---
    PV Name               /dev/sda
    VG Name               vg_virtual_02
    PV Size               16.37 TiB / not usable 2.25 MiB
    Allocatable           yes
    PE Size               4.00 MiB
    Total PE              4291533
    Free PE               1525709
    Allocated PE          2765824
    PV UUID               BlYvJW-ieVx-AjRg-p3r6-e4oC-TkPc-u2lf7x
    

    输出:

    $ ./gg.pl
    ---
    可分配:是
    分配的PE:460544
    免费PE:3830989
    PE 大小:4.00 MiB
    PV 名称:/dev/sdb
    PV 大小:16.37 TiB / 不可用 2.25 MiB
    PV UUID:zqi1Q6-tIag-ghQy-MmdJ-kyOS-XkmY-HpyQ51
    总PE:4291533
    虚拟机名称:vg_virtual_01
    ---
    可分配:是
    分配PE:2765824
    免费PE:1525709
    PE 大小:4.00 MiB
    PV 名称:/dev/sda
    PV 大小:16.37 TiB / 不可用 2.25 MiB
    PV UUID:BlYvJW-ieVx-AjRg-p3r6-e4oC-TkPc-u2lf7x
    总PE:4291533
    VG名称:vg_virtual_02

    【讨论】:

      猜你喜欢
      • 2017-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-11
      • 2017-05-01
      • 2019-04-13
      • 2020-09-21
      • 1970-01-01
      相关资源
      最近更新 更多