【问题标题】:Split string with shifting pattern in perl在perl中使用移位模式拆分字符串
【发布时间】:2014-06-02 19:56:31
【问题描述】:

我有:

my $string = aaaa bbbb "ccccc ddddd eeee" fffff "ggggg hhhh";

我想将此字符串拆分为:

aaaa    
bbbb
cccc dddd eeee
ffff
gggg hhhh

我如何使用拆分来做到这一点?

我认为它应该看起来像这样的伪代码:

split(/IF ONWARD SYMBOL " APPEARS EVENT COUNT DO PATTERN: \s ELSE: "/ $string);

注意:需要保留字符串中字符的顺序

【问题讨论】:

  • 你的代码哪里出错了?

标签: regex string perl split


【解决方案1】:

您可以使用 Perl 核心库中的便捷模块 Text::ParseWords 来做到这一点:

use strict;
use warnings;
use Data::Dumper;
use Text::ParseWords;

my $string = qq(aaaa bbbb "ccccc ddddd eeee" fffff "ggggg hhhh");
my @parts = quotewords('\s+', 0, $string);
print Dumper \@parts;

输出:

$VAR1 = [
          'aaaa',
          'bbbb',
          'ccccc ddddd eeee',
          'fffff',
          'ggggg hhhh'
        ];

【讨论】:

    【解决方案2】:

    与其使用split,不如使用全局正则表达式将字符串划分为带引号和不带引号的部分。

    use strict;
    use warnings;
    
    my $string = 'aaaa bbbb "ccccc ddddd eeee" fffff "ggggg hhhh"';
    
    my @split = $string =~ / " [^"]* " | \S+ /xg;
    
    print "$_\n" for @split;
    

    输出

    aaaa
    bbbb
    "ccccc ddddd eeee"
    fffff
    "ggggg hhhh"
    

    【讨论】:

      【解决方案3】:

      一种拆分方式:

      use strict;
      use warnings;
      
      my $string = '"aaaa" bbbb kkkk "ccccc ddddd eeee" fffff eeee "ggggg hhhh"';
      
      my @res = grep {$_} split(/ *"([^"]*)" *| +/, $string);
      
      print join($/, @res);
      

      【讨论】:

        【解决方案4】:

        您可以分别匹配双引号内和外的单词,并在循环中使用/g,如下所示:

        #!/usr/bin/perl
        
        use strict;
        use warnings;
        
        my $string = 'aaaa bbbb "ccccc ddddd eeee" fffff "ggggg hhhh"';
        
        while ($string =~ m/(\w+)|"([^"]+)"/g) {
            print $1 || $2, "\n";
        }
        

        跑步:

        $ perl t.pl 
        aaaa
        bbbb
        ccccc ddddd eeee
        fffff
        ggggg hhhh
        

        顺便说一句,你只需一行就可以实现上述目标:

        @field = grep { defined } ( $string =~ m/(\w+)|"([^"]+)"/g );
        

        【讨论】:

        • 我确定示例字符串不是实时数据,很可能真实数据字段与\w+ 不匹配
        • 请注意,您可以在此处使用 branch reset 模式(?| ... ),它的作用是将所有捕获存储在备选列表中到同一个变量中。所以m/ (?| (\w+) | "([^"]+)" ) /xg 将设置$1 而不管哪个分支实际匹配。你也可以在while 循环中只写print $1 || $2
        • @Borodin 非常感谢您的建议。答案更新了,第一个版本现在好多了。 (?| ... ) 在 Perl 5.10.0 中引入,但不幸的是我现在使用的是 Perl 5.8.8。不过,知道了还是不错的,谢谢。
        猜你喜欢
        • 2018-10-23
        • 2013-11-08
        • 1970-01-01
        • 1970-01-01
        • 2013-07-07
        • 2012-10-13
        • 1970-01-01
        • 2012-07-30
        • 2019-04-28
        相关资源
        最近更新 更多