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