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

时间:2021-06-07 16:51:10

I got a headache looking for this: How do you use s/// in an expression as opposed to an assignment. To clarify what I mean, I'm looking for a perl equivalent of python's re.sub(...) when used in the following context:

我很头疼地寻找这个:你如何在表达式中使用s ///而不是赋值。为了澄清我的意思,我在下面的上下文中使用时,我正在寻找一个perl等效的python的re.sub(...):

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

The only way I know how to do this in perl so far is:

到目前为止,我知道如何在perl中执行此操作的唯一方法是:

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

Note the extra assignment.

请注意额外的分配。

5 个解决方案

#1


7  

You seem to have a misconception about how =~ works. =~ is a binding operator that associates a variable with a regexp operator. It does not do any assignment.

你似乎对如何运作有误解。 =〜是一个绑定运算符,它将变量与regexp运算符相关联。它没有做任何任务。

The regexp operators all work by default with the topic variable $_, so s/foo/bar/; is the same as $_ =~ s/foo/bar/;. No assignment occurs. The topic variable is transformed.

regexp运算符默认使用主题变量$ _,所以s / foo / bar /;与$ _ = ~s / foo / bar /;相同。没有分配。主题变量已转换。

The case is analogous when operating on any other variable. $var =~ s/foo/bar/; transforms $var by replacing the first instance of foo with bar. No assignment occurs.

在对任何其他变量进行操作时,情况类似。 $ var = ~s / foo / bar /;通过用bar替换foo的第一个实例来转换$ var。没有分配。

The best advice I can give you is to write Python in Python and Perl in Perl. Don't expect the two languages to be the same.

我能给你的最好建议是用Python编写Python,用Perl编写Perl。不要指望两种语言是一样的。

You could do like DVK suggests and write a subroutine that will reproduce the substitution behavior you are used to.

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

Or you could try some idiomatic Perl. Based on your expressed desire to apply multiple transformations in one line, I've provided a couple examples you might find useful.

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

Here I use a for loop over one item to topicalize $var and apply many hard-coded transformations:

在这里,我在一个项目上使用for循环来主题化$ var并应用许多硬编码转换:

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

Or maybe you need to apply a variable group of transforms. I define a subroutine to loop over a list of array references that define old/new transformation pairs. This example takes advantage of Perl's list oriented argument processing to handle any number of transformations.

或者您可能需要应用一组可变的变换。我定义了一个子例程来循环定义旧/新转换对的数组引用列表。此示例利用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;
}

Finally a bit of messing about to provide a version of transform that modifies its first argument:

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

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/;
    }
}

For my own project I'd probably use one of the first two options depending on the needs of the particular problem.

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

#2


11  

You can use ($new = $old) =~ s/whatever/whateverelse/; for an exactly same functionality you are looking for:

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

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

Produces:

生产:

old=OLD, new=NEW

Exactly what you want

正是你想要的

If you're looking for a function, you can just define your own to avoid assignment:

如果您正在寻找一个功能,您可以定义自己的功能以避免分配:

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";

Results in new=cd.

结果在new = cd。

#3


7  

Perl's regular expression substitution always happens 'in-place'. So you need to copy the string to a new variable and operate on the new variable:

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

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

#4


2  

You want to have $newstring be the result of the substitution, right?

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

Something like this:

像这样的东西:

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

Should work. The assignment sets $newstring to $oldstring and then evaluates to $newstring, which is what the substitution acts on.

应该管用。赋值将$ newstring设置为$ oldstring,然后计算为$ newstring,这就是替换所依据的行为。

#5


1  

Based on this, am I right to assume that you cannot have two s/// in one line, one which uses the result of the other, with no intermediate assignments? – mikeY

基于此,我是否正确地假设你不能在一行中有两个// //,一个使用另一个的结果,没有中间分配? - 迈克

Yes you are correct. If you want to apply multiple substitutions to the same string I would do

是的,你是对的。如果你想对我要做的同一个字符串应用多个替换

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

The following won't work because s// returns the number of substitutions made, not the changed string.

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

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

In summary, Perl's regex operations are very different to Python's and you are better trying to learn what Perl does from scratch rather than trying to map Python concepts onto Perl

总之,Perl的正则表达式操作与Python非常不同,您最好尝试从头开始学习Perl的功能,而不是尝试将Python概念映射到Perl上

#1


7  

You seem to have a misconception about how =~ works. =~ is a binding operator that associates a variable with a regexp operator. It does not do any assignment.

你似乎对如何运作有误解。 =〜是一个绑定运算符,它将变量与regexp运算符相关联。它没有做任何任务。

The regexp operators all work by default with the topic variable $_, so s/foo/bar/; is the same as $_ =~ s/foo/bar/;. No assignment occurs. The topic variable is transformed.

regexp运算符默认使用主题变量$ _,所以s / foo / bar /;与$ _ = ~s / foo / bar /;相同。没有分配。主题变量已转换。

The case is analogous when operating on any other variable. $var =~ s/foo/bar/; transforms $var by replacing the first instance of foo with bar. No assignment occurs.

在对任何其他变量进行操作时,情况类似。 $ var = ~s / foo / bar /;通过用bar替换foo的第一个实例来转换$ var。没有分配。

The best advice I can give you is to write Python in Python and Perl in Perl. Don't expect the two languages to be the same.

我能给你的最好建议是用Python编写Python,用Perl编写Perl。不要指望两种语言是一样的。

You could do like DVK suggests and write a subroutine that will reproduce the substitution behavior you are used to.

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

Or you could try some idiomatic Perl. Based on your expressed desire to apply multiple transformations in one line, I've provided a couple examples you might find useful.

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

Here I use a for loop over one item to topicalize $var and apply many hard-coded transformations:

在这里,我在一个项目上使用for循环来主题化$ var并应用许多硬编码转换:

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

Or maybe you need to apply a variable group of transforms. I define a subroutine to loop over a list of array references that define old/new transformation pairs. This example takes advantage of Perl's list oriented argument processing to handle any number of transformations.

或者您可能需要应用一组可变的变换。我定义了一个子例程来循环定义旧/新转换对的数组引用列表。此示例利用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;
}

Finally a bit of messing about to provide a version of transform that modifies its first argument:

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

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/;
    }
}

For my own project I'd probably use one of the first two options depending on the needs of the particular problem.

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

#2


11  

You can use ($new = $old) =~ s/whatever/whateverelse/; for an exactly same functionality you are looking for:

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

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

Produces:

生产:

old=OLD, new=NEW

Exactly what you want

正是你想要的

If you're looking for a function, you can just define your own to avoid assignment:

如果您正在寻找一个功能,您可以定义自己的功能以避免分配:

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";

Results in new=cd.

结果在new = cd。

#3


7  

Perl's regular expression substitution always happens 'in-place'. So you need to copy the string to a new variable and operate on the new variable:

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

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

#4


2  

You want to have $newstring be the result of the substitution, right?

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

Something like this:

像这样的东西:

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

Should work. The assignment sets $newstring to $oldstring and then evaluates to $newstring, which is what the substitution acts on.

应该管用。赋值将$ newstring设置为$ oldstring,然后计算为$ newstring,这就是替换所依据的行为。

#5


1  

Based on this, am I right to assume that you cannot have two s/// in one line, one which uses the result of the other, with no intermediate assignments? – mikeY

基于此,我是否正确地假设你不能在一行中有两个// //,一个使用另一个的结果,没有中间分配? - 迈克

Yes you are correct. If you want to apply multiple substitutions to the same string I would do

是的,你是对的。如果你想对我要做的同一个字符串应用多个替换

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

The following won't work because s// returns the number of substitutions made, not the changed string.

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

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

In summary, Perl's regex operations are very different to Python's and you are better trying to learn what Perl does from scratch rather than trying to map Python concepts onto Perl

总之,Perl的正则表达式操作与Python非常不同,您最好尝试从头开始学习Perl的功能,而不是尝试将Python概念映射到Perl上