如何替换此列表中的每个项目?

时间:2018-04-09 14:27:28

标签: regex perl

我试图检测并更改以下格式的列表。输入字符串

bla bla
* a
* list
* here
bla * bla
bl**a
* another
* list 

期望的输出:

bla bla
LIST
+ a
+ list
+ here
END
bla * bla
bl**a
LIST
+ another
+ list 
END

在此基础上,我意识到我应该使用另一种解析器,并且正则表达式不是这项工作的最佳工具。尽管如此,它让我很好奇,我想知道这个问题是否可以用正则表达式解决。我可以检测到列表并添加LIST / END标记:

s/((^\* .*\n){2,})/LIST\n\1\nEND/gm;

但是,我如何结束更改列表中的各个项目?有没有办法使用这些量化的捕获组?使用s/^\* /+ /g进行另一次传递是不可能的,因为我只对两个或更多项的列表感兴趣。

2 个答案:

答案 0 :(得分:8)

使用Perl正则表达式(正则表达式)确实可以解决这个问题 嵌套的packake_id old_dat old_location_id new_date new_location_id PACK001 2018-04-03 123 2018-04-04 436 可以解决问题:

s///
$/=undef;
$_=<DATA>;
s{((^\* .*\n){2,})}{
    "LIST\n$1END\n"=~s{^\*}{+}mgr;
}gme;
print ;

__DATA__
bla bla
* a
* list
* here
bla * bla
bl**a
* another
* list 

答案 1 :(得分:1)

最简单的方法是将数据读入哈希值,然后在附加任何新格式的情况下再次写出数据:

#!perl

use strict;
use warnings;

use feature qw(say);

my %structured_list;
my @keys;
my $key;

# read data in storing lists under associated keys as array references
while (my $line = readline(*DATA)) {
  chomp $line;

  if ($line =~ /^\*/) {
    # this could be simplified
    push @{$structured_list{$key}}, $line =~ s/^\*\s*//gr;
  }
  else {
    $key = $line;
    push @keys, $key;
    $structured_list{$key} = [];
  }
}

# read keys back out in order
foreach my $list_key (@keys) {
  if (@{$structured_list{$list_key}}) {
    say $list_key;
    say "LIST";
    foreach my $val (@{$structured_list{$list_key}}) {
      say "+ $val";
    }
    say "END";
  }
  else {
   say $list_key;
  }
}

__DATA__
bla bla
* a
* list
* here
bla * bla
bl**a
* another
* list

输出:

➜  perl test.pl
bla bla
LIST
+ a
+ list
+ here
END
bla * bla
bl**a
LIST
+ another
+ list
END