Perl 中的内联正则表达式替换

发布于 2024-09-11 16:43:10 字数 378 浏览 17 评论 0原文

有没有办法用内联正则表达式替换文本,而不是从变量中获取文本并将其存储在变量中?

我是一个 Perl 初学者。我经常发现自己写

my $foo = $bar;
$foo =~ s/regex/replacement/;
doStuff($foo)

在我真正想写的地方

doStuff($bar->replace(s/regex/replacement/));

或类似的地方,而不是使用临时变量和三行。

有办法做到这一点吗?显然,当正则表达式足够复杂时,将其拆分出来是有意义的,这样可以更好地解释它,但是当它只是 s/\s//g 时,用附加变量使代码变得混乱感觉是错误的。

Is there a way to replace text with a regex inline, rather than taking the text from a variable and storing it in a variable?

I'm a perl beginner. I often find myself writing

my $foo = $bar;
$foo =~ s/regex/replacement/;
doStuff($foo)

where I'd really like to write

doStuff($bar->replace(s/regex/replacement/));

or the like, rather than using a temporary variable and three lines.

Is there a way to do this? Obviously when the regex is sufficiently complicated it makes sense to split it out so it can be better explained, but when it's just s/\s//g it feels wrong to clutter the code with additional variables.

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

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

发布评论

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

评论(6

微暖i 2024-09-18 16:43:10

您确实无法执行您想要的操作,因为替换函数如果有效则返回 1 ,如果无效则返回空字符串。这意味着如果您这样做:

doStuff($foo =~ s/regex/replacement/);

doStuff 函数将使用 1 或空字符串作为参数。如果替换函数有效,则没有理由不能返回结果字符串,而不仅仅是 1。然而,这是 Perl 早期的设计决定。不然的话,这会发生什么呢?

$foo = "widget";
if ($foo =~ s/red/blue/) {
    print "We only sell blue stuff and not red stuff!\n";
}

生成的字符串仍然是 widget,但替换实际上失败了。但是,如果替换返回结果字符串而不是空字符串,则 if 仍为 true。

然后,考虑这种情况:

$bar = "FOO!";
if ($bar =~ s/FOO!//) {
   print "Fixed up \'\$bar\'!\n";
}

$bar 现在是一个空字符串。如果替换返回结果,它将返回一个空字符串。然而,替换实际上成功了,我希望我的 if 为真。

在大多数语言中,替换函数返回结果字符串,并且您必须执行以下操作:

if ($bar != replace("$bar", "/FOO!//")) {
   print "Fixed up \'\$bar''!\n";
}

因此,由于 Perl 设计决策(基本上是为了更好地模仿 awk 语法),因此没有简单的方法做你想做的事的方式。不过,您也可以这样做:

($foo = $bar) =~ s/regex/replacement/;
doStuff($foo);

这将执行 $foo 的就地设置,而无需首先为其分配 $bar 的值。 $bar 将保持不变。

You really can't do what you want because the substitution function returns either a 1 if it worked or an empty string if it didn't work. That means if you did this:

doStuff($foo =~ s/regex/replacement/);

The doStuff function would be using either 1 or an empty string as a parameter. There is no reason why the substitution function couldn't return the resultant string instead of just a 1 if it worked. However, it was a design decision from the earliest days of Perl. Otherwise, what would happen with this?

$foo = "widget";
if ($foo =~ s/red/blue/) {
    print "We only sell blue stuff and not red stuff!\n";
}

The resulting string is still widget, but the substitution actually failed. However, if the substitution returned the resulting string and not an empty string, the if would still be true.

Then, consider this case:

$bar = "FOO!";
if ($bar =~ s/FOO!//) {
   print "Fixed up \'\$bar\'!\n";
}

$bar is now an empty string. If the substitution returned the result, it would return an empty string. Yet, the substitution actually succeeded and I want to my if to be true.

In most languages, the substitution function returns the resulting string, and you'd have to do something like this:

if ($bar != replace("$bar", "/FOO!//")) {
   print "Fixed up \'\$bar''!\n";
}

So, because of a Perl design decision (basically to better mimic awk syntax), there's no easy way to do what you want. However you could have done this:

($foo = $bar) =~ s/regex/replacement/;
doStuff($foo);

That would do an in place setting of $foo without first assigning it the value of $bar. $bar would remain unchanged.

写给空气的情书 2024-09-18 16:43:10

从 perl 5.14 开始,您可以使用 非破坏性替换以实现所需的行为。

使用 /r 修饰符来执行此操作:

doStuff($bar=~s/regex/replacement/r);

Starting from perl 5.14 you can use Non-destructive substitution to achieve desired behavior.

Use /r modifier to do so:

doStuff($bar=~s/regex/replacement/r);
昔梦 2024-09-18 16:43:10
use Algorithm::Loops "Filter";

# leaves $foo unchanged
doStuff( Filter { s/this/that/ } $foo );
use Algorithm::Loops "Filter";

# leaves $foo unchanged
doStuff( Filter { s/this/that/ } $foo );
李不 2024-09-18 16:43:10

您可以使用 do { } 块来避免在当前作用域中创建临时变量:

doStuff( do {(my $foo = $bar) =~ s/regex/replacement/; $foo} );

You can use a do { } block to avoid creating a temporary variable in the current scope:

doStuff( do {(my $foo = $bar) =~ s/regex/replacement/; $foo} );
想你只要分分秒秒 2024-09-18 16:43:10

这是你想要的吗?:

my $foo = 'Replace this with that';
(my $bar = $foo) =~ s/this/that/;
print "Foo: $foo\nBar: $bar\n";

打印:

Foo: Replace this with that
Bar: Replace that with that

Is this what you want?:

my $foo = 'Replace this with that';
(my $bar = $foo) =~ s/this/that/;
print "Foo: $foo\nBar: $bar\n";

Prints:

Foo: Replace this with that
Bar: Replace that with that
安静被遗忘 2024-09-18 16:43:10

还有另一种方法:编写您自己的函数:

sub replace (
    my $variable = shift;
    my $substring = shift;

    eval "\$variable =~ s${substring};";
    return $variable
}

doStuff(replace($foo, "/regex/replace/"));

这​​对于单个调用来说是不值得的,并且在这种情况下可能只会使您的代码更加混乱。但是,如果您执行此操作十几次左右,则编写自己的函数来执行此操作可能更有意义。

There is yet another way: Write your own function:

sub replace (
    my $variable = shift;
    my $substring = shift;

    eval "\$variable =~ s${substring};";
    return $variable
}

doStuff(replace($foo, "/regex/replace/"));

This wouldn't be worth it for a single call, and it would probably just make your code more confusing in that case. However, if you're doing this a dozen or so times, it might make more sense to write your own function to do this.

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