【问题标题】:How do I perform a Perl substitution on a string while keeping the original?如何在保留原始字符串的同时对字符串执行 Perl 替换?
【发布时间】:2010-09-06 13:47:51
【问题描述】:

在 Perl 中,使用正则表达式对字符串执行替换并将值存储在不同变量中而不更改原始值的好方法是什么?

我通常只是将字符串复制到一个新变量,然后将其绑定到对新字符串进行替换的s/// 正则表达式,但我想知道是否有更好的方法来做到这一点?

$newstring = $oldstring;
$newstring =~ s/foo/bar/g;

【问题讨论】:

    标签: regex perl replace


    【解决方案1】:

    这是我一直用来在不更改原始字符串的情况下获取字符串的修改副本的习语:

    (my $newstring = $oldstring) =~ s/foo/bar/g;
    

    在 perl 5.14.0 或更高版本中,您可以使用新的/r non-destructive substitution modifier

    my $newstring = $oldstring =~ s/foo/bar/gr; 
    

    注意:
    上述解决方案也可以在没有g 的情况下使用。它们也适用于任何其他修饰符。

    另请参阅:
    perldoc perlrequick: Perl regular expressions quick start

    【讨论】:

    • 是否使用严格。变量的最小范围++
    • 我想知道像my $new = $_ for $old =~ s/foo/bar; 这样的东西是否可行?
    • @Benoit,我相信你的意思是s/foo/bar/ for my $newstring = $oldstring; 它有效,但它更奇怪。
    【解决方案2】:

    声明:

    (my $newstring = $oldstring) =~ s/foo/bar/g;
    

    相当于:

    my $newstring = $oldstring;
    $newstring =~ s/foo/bar/g;
    

    或者,从 Perl 5.13.2 开始,您可以使用 /r 进行非破坏性替换:

    use 5.013;
    #...
    my $newstring = $oldstring =~ s/foo/bar/gr;
    

    【讨论】:

    • 您是否忘记了顶级正则表达式中的g
    【解决方案3】:

    use strict 下,说:

    (my $new = $original) =~ s/foo/bar/;
    

    改为。

    【讨论】:

      【解决方案4】:

      单行解决方案作为陈词滥调比好的代码更有用;优秀的 Perl 编码人员会知道并理解它,但它的透明度和可读性远不如您开始使用的两行复制和修改对联。

      换句话说,一个很好的方法就是你已经这样做了。以可读性为代价的不必要的简洁不是胜利。

      【讨论】:

      • 嗯,但是单行版本不会出现无意修改错误字符串的问题。
      • 单行版本,如果正确执行,不是主题,是真的。但这是一个单独的问题。
      • 您可能会认为这是不必要的简洁,但必须键入两次变量名才能使用一次它是失败点数的两倍。它对于了解该语言的人来说是完全可读的,甚至在我们的 Learning Perl 课程中。
      【解决方案5】:

      另一个 5.14 之前的解决方案:http://www.perlmonks.org/?node_id=346719(参见 japhy 的帖子)

      由于他的方法使用map,它也适用于数组,但需要级联map 来生成临时数组(否则会修改原始数组):

      my @orig = ('this', 'this sucks', 'what is this?');
      my @list = map { s/this/that/; $_ } map { $_ } @orig;
      # @orig unmodified
      

      【讨论】:

        【解决方案6】:

        如果你用use strict; 编写 Perl,那么你会发现单行语法是无效的,即使在声明时也是如此。

        与:

        my ($newstring = $oldstring) =~ s/foo/bar/;
        

        你得到:

        Can't declare scalar assignment in "my" at script.pl line 7, near ") =~"
        Execution of script.pl aborted due to compilation errors.
        

        相反,您一直使用的语法虽然更长,但在语法上是使用use strict; 的正确方法。对我来说,现在使用use strict; 只是一种习惯。我自动做。每个人都应该这样做。

        #!/usr/bin/env perl -wT
        
        use strict;
        
        my $oldstring = "foo one foo two foo three";
        my $newstring = $oldstring;
        $newstring =~ s/foo/bar/g;
        
        print "$oldstring","\n";
        print "$newstring","\n";
        

        【讨论】:

        • 如果您使用use warnings; 而不是-w,您可以获得更大的控制权:例如,如果您想暂时关闭代码块中的警告。
        【解决方案7】:

        我讨厌 foo 和 bar .. 到底是谁在编程中想出了这些非描述性的术语?

        my $oldstring = "replace donotreplace replace donotreplace replace donotreplace";
        
        my $newstring = $oldstring;
        $newstring =~ s/replace/newword/g; # inplace replacement
        
        print $newstring;
        %: newword donotreplace newword donotreplace newword donotreplace
        

        【讨论】:

        • 这与原版有何不同? (我想你想要=~ s。)
        • Clbuttic 错误。该代码的实际输出是newword donotnewword newword donotnewword newword donotnewword
        • 看...如果 JoGotta 使用的是传统且熟悉的 foobar,他的答案将是准确的。再一次证明,习俗的存在是有原因的,而教训只能通过艰难的方式吸取。 ;)
        • 谁?维基百科有part of the answer。包括:“foobar 的词源可能来源于二战时期的军事俚语 FUBAR,它被贬义为 foobar。更早使用了 foo 这个词本身。...... 1965 年版的 MIT 技术工程新闻中出现了编程上下文中的印刷术语。”
        【解决方案8】:

        如果我只是在 oneliner 中使用它,怎么样,sprintf("%s", $oldstring)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-05-25
          • 2018-12-01
          • 1970-01-01
          • 2019-11-02
          相关资源
          最近更新 更多