使用Perl在同一行中逐步替换一个数字

时间:2013-11-18 04:18:44

标签: perl

我有一些像这样的XML数据

<!--Q1: some text--><!--Q1: some text--><!--Q1: some text-->

我想按顺序替换此查询号

<!--Q1: some text--><!--Q2: some text--><!--Q3: some text-->..

我写了这个Perl脚本

#!/usr/bin/perl -w
$b=1;
use strict;
open(FILE, "<text.xml") || die "File not found";
my @lines = <FILE>;
close(FILE);
my @newlines;
while<> { 
    $_ =~ s/<!--Q[0-9]{1,2}/<!--Q$b/g;
    $b++;
    push(@newlines,$_);
}
open(FILE, ">text.xml") || die "File not found";
print FILE @newlines;

但它只在每一行中进行一次替换。

我的文字:

<!--Q2: text-->
<!--Q3: text--><!--Q8: text-->
<!--Q10: text--> 

输出

<!--Q1: text-->
<!--Q**2**: text--><!--Q**2**: text-->
<!--Q3: text-->

1 个答案:

答案 0 :(得分:3)

您的计划存在许多问题

  • 您必须始终use strictuse warnings作为您计划的第一行

  • 您应该使用词汇文件句柄(标量变量)而不是全局名称

  • 您应该使用open的三参数形式,如果$!失败,则在die字符串中包含内置变量open

  • 永远不会使用$a$b作为变量名称。它们根本没有帮助记录程序,它们由perl内部使用,所以你不能依赖它们的内容

  • 您已将整个文件读入@lines,然后希望在while循环中有更多内容可供阅读。您已经到达文件末尾,因此永远不会输入循环

  • <!--Q之后测试完全一位或两位数是毫无意义的。如果有三位或更多位数的发生,那么正则表达式仍将匹配,但只会替换前两位数字

  • 没有理由push将修改后的行添加到数组中,并print将它们全部放在后面。只需在更改时打印每一个

请改用它。正则表达式中的\K构造需要Perl 5的10.0版。它自2007年以来一直存在,所以如果你落后于你的更新,那么你应该真正解决这个问题。

use strict;
use warnings;
use 5.010;

open my $in,  '<', 'text.xml'    or die $!;
open my $out, '>', 'newtext.xml' or die $!;

my $n = 0;

while (<$in>) {
  s/<!--Q\K\d+/++$n/ge;
  print $out $_;
}

<强>输出

<!--Q1: text-->
<!--Q2: text--><!--Q3: text-->
<!--Q4: text--> 

<强>更新

如果你没有可用的Perl 5版本10(并且你真的应该 - 它是六年旧并且是主要更新)那么你可以像这样编写正则表达式

s/(<!--Q)\d+/$1.++$n/ge;