Regex 正则表达式匹配行并另存为第一行

Regex 正则表达式匹配行并另存为第一行,regex,perl,Regex,Perl,嗨,我一直在尝试编写一个正则表达式来匹配开头“step start”和“step end”之间的文本,然后使用step start之后的第一行将文件另存为,但我似乎无法让正则表达式工作。我正在使用Perl来实现它,但我也可以使用JavaScript函数 正则表达式 样本数据 step start Block 1+ DMC-GAASIB0-00-48-21-02-01AAA-520A-A.xml DMC-GAASIB0-00-48-21-02-01AAA-720A-A.xml step end s

嗨,我一直在尝试编写一个正则表达式来匹配开头“step start”和“step end”之间的文本,然后使用step start之后的第一行将文件另存为,但我似乎无法让正则表达式工作。我正在使用Perl来实现它,但我也可以使用JavaScript函数

正则表达式

样本数据

step start
Block 1+
DMC-GAASIB0-00-48-21-02-01AAA-520A-A.xml
DMC-GAASIB0-00-48-21-02-01AAA-720A-A.xml
step end
step start
4026 through 4167 and 4170 through 4207
DMC-GAASIB0-00-79-11-01-00AAA-941A-A.xml
step end
4108 through 4124 and Block 1+
DMC-GAASIB0-00-91-28-00-19AAA-051A-A.xml
step end
step start
4242 through 4606
DMC-GAASIB0-03-48-21-02-01AAA-520A-A.xml
DMC-GAASIB0-03-48-21-02-01AAA-720A-A.xml
step end
step start
Aircraft 4010 through 4124
DMC-GAASIB0-00-08-41-01-00AAA-169F-A.xml
DMC-GAASIB0-00-08-41-03-00AAA-023A-A.xml
DMC-GAASIB0-00-91-93-7A-12AAA-051A-A.xml
step end

谢谢您的帮助。

您需要在重复组中包含
\R
,并使其延迟,以避免匹配重叠的开始/结束块:

^step start\R(\w.+)\R(?:\w.+\R)*?step end$

非捕获组
(?:\w.+\R)*?
允许在末尾换行,以允许在匹配
步骤结束之前匹配多行


另外,在
步骤结束后使用
$
也是安全的。我建议先匹配整个中间文本块,然后提取第一行。否则,您的
\w.+\w
模式可能会无意中匹配
步骤结束
,并跳到下一个块。比如说,

if ($string =~ /^step start\n(.*?)^step end$/ms) {
    my $block = $1;
    my $first_line;
    if ($block =~ s/\A(.*)\n//) {
        $first_line = $1;
    }
    ...
}
步进启动
台阶端
步进起动
福
bar.xml
台阶端
否则将被解析为一个单独的块,文件名(第一行)为
step end

if ($string =~ /^step start\n(.*?)^step end$/ms) {
    my $block = $1;
    my $first_line;
    if ($block =~ s/\A(.*)\n//) {
        $first_line = $1;
    }
    ...
}
这里的
*?
模式(与
s
标志结合使用)匹配“所有文本,但尽可能少”

或者,您可以在
“\n步骤结束\n”
上拆分输入,并从每个块中删除标题:

for my $block (split /^step end\n/m, $string) {
    $block =~ s/\Astep start\n(.*)\n//
        or next;  # malformed block
    my $first_line = $1;
    ...
}

我的观点是,对于您正在做的事情,直接正则表达式解决方案不够健壮。首先,它似乎要求您在尝试匹配之前将整个文件拖到内存中,这对于大型输入是不可伸缩的。这是一个一次性解决方案,它不会使文件名带有空格(替换为
):


\R(\w.++\w)\R(\w.++\w)+
应该做什么?是否执行两个单独的匹配:一个用于文件名,一个用于文件内容?是否缺少
4108到4124
之前的
步骤开始
,或者数据是这样的?我无法使正则表达式对字符串“Block 1+”起作用。我很欣赏你的想法谢谢你,太棒了!无法正确处理空的或一个行块。我不是指同一行,我是指
“step start\n foo bar\n step end\n”
@anubhava它在包含1 Begin 1+的行上不起作用。@anubhava我已编辑测试数据以反映块1+
perl -ne '
  if($n==1){
    ($f=$_)=~s/\s/_/g;
    chop $f;
    open F,">$f";
  }
  if(/^step start/){
    $n=1;
  }
  elsif(!/^step end/){
    print F $_;
    ++$n;
  }'