代码之家  ›  专栏  ›  技术社区  ›  Mansour

如何在表达式中使用perl的///?

  •  7
  • Mansour  · 技术社区  · 14 年前

    我很头疼找这个: 如何在表达式中使用s///而不是赋值。为了澄清我的意思,我正在寻找一个与python等价的perl 子(…) 在以下上下文中使用时:

    newstring = re.sub('ab', 'cd', oldstring)
    

    到目前为止,我知道在Perl中如何做到这一点的唯一方法是:

    $oldstring =~ s/ab/cd/;
    $newstring = $oldstring;
    

    注意额外的任务。

    5 回复  |  直到 14 年前
        1
  •  7
  •   daotoad    14 年前

    你似乎对如何 =~ 作品。 = 是将变量与regexp运算符关联的绑定运算符。它不做任何分配。

    默认情况下,regexp运算符都使用topic变量 $_ 如此 s/foo/bar/; $_ =~ s/foo/bar/; . 不进行分配。主题变量被转换。

    当操作任何其他变量时,情况类似。 $var =~ s/foo/bar/; 变换 $var 通过替换 foo 具有 bar . 不进行分配。

    我能给你的最好建议是用python编写python,用perl编写perl。别指望这两种语言是一样的。

    您可以像dvk建议的那样,编写一个子例程来重现您习惯的替换行为。

    或者您可以尝试一些惯用的Perl。基于您希望在一行中应用多个转换的愿望,我提供了几个您可能会发现有用的示例。

    这里我用的是 for 将一个项目循环到主题化 var 并应用许多硬编码转换:

    for( $var ) {
        s/foo/bar/;
        s/fizz/buzz/;
        s/whop/bop-a-loo-bop/;
        s/parkay/butter/;
        s/cow/burger/;
    }
    

    或者您可能需要应用一组变量转换。我定义了一个子程序来循环定义旧/新转换对的数组引用列表。本例利用Perl面向列表的参数处理来处理任意数量的转换。

    my $foo = transform(
        'abcd' =>
        [ 'a',  'b'    ], 
        [ 'bb', 'c'    ],
        [ 'cc', 'd'    ],
        [ 'dd', 'DONE' ],
    );
    
    sub transform {
        my $var = shift;
        for (@_ ) {
            my ($old, $new) = @$_;
            $var =~ s/$old/$new/;
        }
    
        return $var;
    }
    

    最后,有点搞乱了如何提供修改其第一个参数的转换版本:

    my $foo = 'abcd';
    
    transform_in_place(
        $foo =>
        [ 'a',  'b'    ], 
        [ 'bb', 'c'    ],
        [ 'cc', 'd'    ],
        [ 'dd', 'DONE' ],
    );
    
    print "$foo\n";
    
    sub transform_in_place {
        for my $i (1..$#_ ) {
            my ($old, $new) = @{$_[$i]};
            $_[0] =~ s/$old/$new/;
        }
    }
    

    对于我自己的项目,我可能会根据特定问题的需要使用前两个选项中的一个。

        2
  •  11
  •   DVK    14 年前

    你可以使用 ($new = $old) =~ s/whatever/whateverelse/; 对于您正在寻找的完全相同的功能:

    use strict;
    my $old = "OLD";
    my $new;
    ($new = $old) =~ s/OLD/NEW/;
    print "old=$old, new=$new";
    

    生产:

    old=OLD, new=NEW
    

    正是你想要的

    如果您正在寻找一个函数,您可以定义自己的函数以避免赋值:

    use strict;
    sub re_sub { 
       my ($find, $replace, $old) = @_;
       my $new = $old;
       $new =~ s/$find/$replace/;
       return $new;
    }
    
    my $old = "ab";
    my $new = re_sub('ab', 'cd', $old);
    print "new=$new\n";
    

    结果在 new=cd .

        3
  •  7
  •   Grant McLean    14 年前

    Perl的正则表达式替换总是“就地”发生。因此,您需要将字符串复制到新变量并对新变量进行操作:

    (my $newstring = $oldstring) =~ s/ab/cd/;
    
        4
  •  2
  •   jade Michael Borgwardt    14 年前

    你想让$newstring成为替换的结果,对吧?

    像这样的:

    ($newstring = $oldstring) =~ s/ab/cd;
    

    应该有用。作业集 $newstring $oldstring 然后评估为 $新字符串 ,这就是替换作用。

        5
  •  1
  •   justintime    14 年前

    基于此,我是否可以假设一行中不能有两个s///,一个使用另一个的结果,没有中间赋值?米奇

    是的,你是对的。 如果要对同一字符串应用多个替换,我将执行以下操作

        $newstring = $oldstring ;
        $newstring  =~ s/ab/cd/ ;
        $newstring  =~ s/xx/yy/ ;
    

    以下方法不起作用,因为 s// 返回所做替换的数目,而不是更改的字符串。

        $newstring = $oldstring) =~ s/ab/cd/ =~ s/xx/yy/ ;
    

    总之,perl的regex操作与python的非常不同,您最好从头开始学习perl的功能,而不是将python概念映射到perl上