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

Regex 如何替换此列表中的每个项目?,regex,perl,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 在进行这项工作时,我意识到我应该使用另一种解析器,而regex并不是完成这项工作的最佳工具。不过,这让我很好奇,我想知道这个问题是否可以用正则表达式解决。我可以

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

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
在进行这项工作时,我意识到我应该使用另一种解析器,而regex并不是完成这项工作的最佳工具。不过,这让我很好奇,我想知道这个问题是否可以用正则表达式解决。我可以检测列表并添加列表/结束标记:

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

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

最简单的方法是将数据读入散列,然后再次写出数据,并附加任何新格式:

#!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

使用Perl正则表达式(regex)确实可以解决这个问题。
嵌套的
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 

正则表达式是解决方案的一部分,但不是解决方案。您需要编写一个程序,通过您的输入工作,检测列表的开头和结尾,然后执行您想要的操作。诀窍是一行一行地做。每行都有几个选项。您可以位于列表的开头、末尾、列表中或不在列表中。重复捕获组不起作用,因为它们只保留匹配的最后一次出现:匹配
(\w)+
over
abc
将使第一个捕获组保留
c
@simbabque是的,这正是我的意思。对不起,我不清楚。我有一个使用“解析器”的工作解决方案。我很想扩展我的正则表达式知识。你可能可以使用lookarounds来区分你是在列表的开头、中间还是结尾(只需检查你是在前面还是在后面);这三种情况只匹配一个列表项,因此您可以使用捕获组替换列表项中的固定模式感谢您的努力,很抱歉不清楚。我有一个逐行“解析器”的工作解决方案。我很想扩展我的正则表达式知识。从技术上讲,这是Perl,而不是正则表达式@我认为,问题中的simbabque regex术语指的是Perl regex,而不是SO标记所包含的内容。但我还是找到了答案。@wolfrevokcats:太棒了+1.
bla bla
LIST
+ a
+ list
+ here
END
bla * bla
bl**a
LIST
+ another
+ list
END