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

发布于 2024-08-29 17:04:23 字数 311 浏览 5 评论 0原文

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

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

我知道如何在 perl 中执行此操作的唯一方法,所以far 是:

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

注意额外的分配。

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:

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

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

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

Note the extra assignment.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

乖乖兔^ω^ 2024-09-05 17:04:23

您可以使用 ($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

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

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.

音栖息无 2024-09-05 17:04:23

您似乎对 =~ 的工作原理有误解。 =~ 是将变量与正则表达式运算符关联起来的绑定运​​算符。它不执行任何任务。

默认情况下,正则表达式运算符都与主题变量 $_ 一起使用,因此 s/foo/bar/;$_ =~ s/foo 相同/栏/;。没有分配发生。主题变量已转换。

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

我能给你的最好建议是用 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/;
    }
}

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

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.

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.

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.

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.

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

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.

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

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.

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.

苍风燃霜 2024-09-05 17:04:23

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

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

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:

(my $newstring = $oldstring) =~ s/ab/cd/;
短暂陪伴 2024-09-05 17:04:23

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

像这样的事情:

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

应该有效。该赋值将 $newstring 设置为 $oldstring,然后计算结果为 $newstring,这就是替换的作用。

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

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.

输什么也不输骨气 2024-09-05 17:04:23

基于此,我是否可以假设一行中不能有两个 s///,其中一个使用另一个的结果,而没有中间赋值,这是正确的吗? – mikeY

是的,你是对的。
如果您想对同一个字符串应用多个替换,我会执行

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

以下操作,因为 s// 返回所做的替换数,而不是更改后的字符串。

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

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

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.

    $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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文