我有一些文本,如下所示.我需要对它做一个基本的编辑,但无法理解我需要的正则表达式.也许这只是漫长的一天,我没有看到我需要的东西.
样本数据:
START ITEM = 1235
BEGIN
WORD
RATE = 98
MORE WORDS
CODE = XX
STUFF
END
BEGIN
TEXT
MORE WORDS
RATE = 57
ADDITIONAL TEXT
CODE = YY
OTHER THINGS
END
STOP
START ITEM = 9983
BEGIN
WORD
RATE = 01
MORE WORDS
CODE = AA
STUFF
END
BEGIN
TEXT
MORE WORDS
RATE = 99
ADDITIONAL TEXT
CODE = XX
OTHER THINGS
END
STOP
Run Code Online (Sandbox Code Playgroud)
我给了一个CODE和一个ITEM数字,需要在相应的BEGIN/ END部分编辑速率.幸运的是,这些部分定义为STOP/ START BEGIN/ END(它们是关键字,而不是其他任何地方).
我的工具箱是Perl正则表达式.*
我尝试的第一个解决方案不起作用(值硬编码):
$tx =~ s/(START \s ITEM \s = \s 9983.*?
BEGIN
.*?
RATE \s = \s )\d+
(.*? # Goes too far
CODE \s = \s XX)
/$1$newRate$2
/sx;
Run Code Online (Sandbox Code Playgroud)
因为指示的代码过多地匹配,找到更正确的代码但总是编辑第一个条目.
建议?
*实际代码依赖于正则表达式被添加到一堆正则表达式(一种后处理过滤器)上,每个正则表达式依次应用于文本进行编辑.哎呀,如果我有文字,我可以做一个全功能的解析器.但是我希望不要打破这个代码并坚持使用我已经拥有的API.
正则表达式不适合这类问题.我推荐一个简单的迭代解决方案:
while (<FILE>) {
# push lines straight to output until we find the START that we want
print OUT $_;
next unless m/START ITEM = $number/;
# save the lines until we get to the CODE that we want
my @lines;
while (<FILE>)
{
push @lines, $_;
last if m/CODE = $code/;
}
# @lines now has everything from the START to the CODE. Get the last RATE in
# @lines and change its value.
my $strref = \( grep m/RATE/ @lines )[-1];
$$strref = $new_value;
# print out the lines we saved and exit the loop
print OUT @lines;
last;
}
Run Code Online (Sandbox Code Playgroud)
编辑:如果你真的想要一个正则表达式,你可以使用这样的东西(未经测试):
$tx =~ s/(START \s+ ITEM \s+ = \s+ 9983.*?
BEGIN
.*?
RATE \s+ = \s+ )\d+
( (?: (?! END ) . )*
CODE \s+ = \s+ XX)
/$1$newRate$2
/sx;
Run Code Online (Sandbox Code Playgroud)
添加的(?: (?! END ) . )*确保RATE和CODE之间的匹配不会越过END.但这将比非正则表达式方法慢得多.
| 归档时间: |
|
| 查看次数: |
231 次 |
| 最近记录: |