【问题标题】:How do I replace a token with increasing numbers in Perl?如何用Perl中的越来越多的数字替换令牌?
【发布时间】:2010-10-18 20:46:01
【问题描述】:

我想用数字替换文本文件中的标记。令牌是“<count>”,我希望将其替换为到目前为止的计数。例如:

This <count> is a <count> count.
The <count> count increases <count><count><count>.
<count><count><count><count><count><count>

变成:

This 1 is a 2 count.
The 3 count increases 456.
789101112

我不太确定该怎么做,也许有一些循环?

my $text = (the input from file, already taken care of in my script);
my $count = 1;
while( regex not found? )
{
    $text =~ s/<count>/($count);
    $count ++;
}

【问题讨论】:

    标签: perl string


    【解决方案1】:
    my $text = "whatever";
    my $count = 1;
    $text =~ s/<count>/$count++/ge;
    

    应该为你做。替换结束时的 /e 会有所不同。

    【讨论】:

      【解决方案2】:

      这是一个 procFile 脚本,可以满足您的要求:

      $val = 1;                         # Initial change value.
      while (<STDIN>) {                 # Process all lines.
          chomp;                        # Remove linefeed.
          $ln = $_;                     # Save it.
          $oldln = "x" . $ln;           # Force entry into loop.
          while ($oldln ne $ln) {       # Loop until no more changes.
              $oldln = $ln;             # Set lines the same.
              $ln =~ s/<count>/$val/;   # Change one occurrence if we can.
              if ($oldln ne $ln) {      # Increment count if change was made.
                  $val++;
              }
          }
          print "$ln\n";                # Print changed line.
      }
      

      您使用cat inputFile | perl procFile 和您的示例文件运行它:

      This <count> is a <count> count.
      The <count> count increases <count><count><count>.
      <count><count><count><count><count><count>
      

      生成:

      This 1 is a 2 count.
      The 3 count increases 456.
      789101112
      

      【讨论】:

        【解决方案3】:

        这是另一种使用位置扫描的方法。

        它使用 \G 位置引用来匹配行的开头或上一个匹配之后的位置。

        #!/usr/bin/perl 
        use strict;      # always strict + warnings 
        use warnings;
        
        my $count = 1;   # start at 1; 
        
        while ( my $line = <STDIN> ) {                            # read stdin 
            while ( $line =~ /\G.*?(<count>)/g ) {                 # scan left to right and pick out one <count> at a time.
                substr( $line, $-[1], $+[1] - $-[1], $count++ );  # replace the substring and increment
            }
            print $line;
        }
        

        它的功能几乎与发布的 regex-eval 解决方案相同,只是它在没有 eval 的情况下工作。我之前发布了一些反评估的恐惧,但它只是来自其他较小语言的 FUD 并没有安全地进行评估。

        /e 方式有效地做到了这一点:

        replace_callback( \$input, $regex, sub{ 
           return $count++;
        }); 
        

        (其中替换回调是一个完成所有工作的臃肿函数)

        这真的像鸡蛋一样安全,只是不明显它是否安全。

        【讨论】:

        • 是的,/e 是一个 eval,但它是一个 eval BLOCK,而不是一个 eval EXPR; eval BLOCK 非常安全(它只是捕获错误的方法),人们不应该偏执地使用它。
        • 我在这个答案中没有看到任何 5.10 功能。
        • 我认为 $- 和 $+ 在 5.10 中是新的,也许我错了:)。而且我似乎已经知道 regexp eval 以某种方式是基于字符串的(可能基于语法高亮显示它的方式)
        • 哦,检查 perldelta,我看错了,@+ 和 @- 只是行为发生了变化。并且 \G 也不是新的,声明已编辑。
        • 而我的 javascript + php 过去让我对 eval 产生了毒害:/,因为在那些语言中,它几乎总是是错误的选择。
        猜你喜欢
        • 2017-03-22
        • 1970-01-01
        • 2019-05-15
        • 2018-08-12
        • 2015-11-29
        • 1970-01-01
        • 1970-01-01
        • 2021-12-13
        • 2021-12-18
        相关资源
        最近更新 更多