13

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

我是 perl 初学者。我经常发现自己在写作

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

我真的很想写的地方

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

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

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

4

6 回答 6

14

你真的不能做你想做的事情,因为如果替换函数有效则返回 a 1,如果无效则返回空字符串。这意味着如果你这样做:

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

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

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

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

然后,考虑这种情况:

$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将保持不变。

于 2010-07-25T21:20:34.107 回答
9

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

使用/r修饰符这样做:

doStuff($bar=~s/regex/replacement/r);
于 2016-08-10T07:36:27.843 回答
5
use Algorithm::Loops "Filter";

# leaves $foo unchanged
doStuff( Filter { s/this/that/ } $foo );
于 2010-07-26T00:48:12.173 回答
2

您可以使用do { }块来避免在当前范围内创建临时变量:

doStuff( do {(my $foo = $bar) =~ s/regex/replacement/; $foo} );
于 2010-07-25T20:43:51.600 回答
0

这是你想要的吗?:

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
于 2010-07-25T20:52:48.447 回答
-1

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

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

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

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

这对于一次调用来说是不值得的,在这种情况下它可能只会让你的代码更加混乱。但是,如果您要这样做十几次,编写自己的函数来执行此操作可能更有意义。

于 2010-07-25T21:35:28.440 回答