我所做的所有搜索都在 sed 或 awk 中给出了答案,但我想要纯 Perl 解决方案。 我想在匹配后修改下面的文本。
opts@FieldTitle = "mcape"
opts@MainTitle = "MCAPE: NODA~C~Valid:" + dystr(it) + "/" + mnstr(it) + "/" + yrstr(it) + "Issued:" + dystr(0) + "/" + mnstr(0) + "/" + yrstr(0)
opts@ContourParameters = (/ 500., 3000., 250./)
opts@FieldTitle = "mcin"
opts@MainTitle = "MCIN: NODA~C~Valid:" + dystr(it) + "/" + mnstr(it) + "/" + yrstr(it) + "Issued:" + dystr(0) + "/" + mnstr(0) + "/" + yrstr(0)
opts@ContourParameters = (/ 0., 125., 25./)
我立即阅读了整个文件
@scrptlines=<$NCLSCRPT>;
然后我还有其他替代品可供使用
foreach $scrptlines (@scrptlines){
$scrptlines =~ s/DATADir =.*/DATADir = "$INPUT_DIR[$kk]\/"/g; #e.g.
当我看到上面几行时,我已经尝试过
if($scrptlines =~ m/opts\@FieldTitle = "mcape"/){
next unless($scrptlines =~ m/opts\@MainTitle/);
$scrptlines =~ s/opts\@MainTitle =.*/opts\@MainTitle = "MCIN: NODA~C~Valid:" + dystr(it) + "\/" + mnstr(it) + "\/" + yrstr(it) + "Issued:" + dystr(0) + "\/" + mnstr(0) + "\/" + yrstr(0)/;
}
然后尝试
if($scrptlines =~ m/opts\@FieldTitle = "mcape"/){
$scrptlines =~/opts@FieldTitle = "mcape"/{n;s\/opts\@MainTitle =.*/opts@MainTitle = "MCIN: NODA~C~Valid:" + dystr(it) + "\/" + mnstr(it) + "\/" + yrstr(it) + "Issued:" + dystr(0) + "\/" + mnstr(0) + "\/" + yrstr(0)/};
两者都不起作用,加上我所做的其他尝试。
最佳答案
当该行匹配时,将“标志”(变量)设置为 true,否则保持为 false。然后,如果该标志为 true,您可以进行所需的更改,设置后的下一次迭代中将发生什么,因此对于文件中的下一行。
my $saw_trigger_line;
foreach my $line (@scrptlines) {
if ($saw_trigger_line) {
# Do what is needed
# If it's all done then unset the flag for the future operation
$saw_trigger_line = 0;
}
...
# Sets the flag to true if line matches
$saw_trigger_line = $line =~ /opts\@FieldTitle = "mcape"/;
}
可以通过将正则表达式的匹配运算符的返回值分配给该标志来设置该标志,因为该运算符本身(表达式 $var =~/.../
)返回 true 或 false (通常为 1
或 ''
)。
我们需要首先测试该标志(如果为真,则执行所需的操作),以便查看它是否在上一次迭代中设置,并且仅在循环的稍后部分重新评估它(设置或再次取消设置)。为此,我们可以在循环结束时设置标志,以便它在下一次迭代中具有该值。
关于perl - 在 perl 中替换匹配后的下一行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76048997/