我想知道在perl正则表达式中使用常量。我想做一些类似的事情:
use constant FOO => "foo"
use constant BAR => "bar"
$somvar =~ s/prefix1_FOO/prefix2_BAR/g;
当然,在这里,FOO
解析为三个字母F
O
O
,而不是扩展为常数。
我在网上查了一下,有人建议使用${\FOO}
或@{[FOO]}
,还有人提到了(?{FOO})
。我想知道是否有人可以阐明哪些是正确的,以及是否有任何优势。或者,只使用非常数变量是否更好?(在我的情况下,性能是一个因素)。
4条答案
按热度按时间rlcwz9us1#
没有太多的理由使用常量而不是变量。这并没有太大的区别-
perl
无论如何都会编译一个正则表达式。例如:
提供:
真的没什么好担心的。
然而,值得注意的是,你可以用
qr//
编译正则表达式,这样做--假设RE是静态的--可能会提高性能(但可能不会,因为perl * 可以 * 检测静态正则表达式,并且它本身就能做到。代码如下:
不过说实话,这是一个微观优化。与您的代码相比,正则表达式引擎的速度很快,所以不必担心。如果性能对你的代码至关重要,那么处理它的正确方法是 * 首先 * 编写代码,然后 * 分析它以寻找要优化的热点。
v440hwme2#
所显示的问题是由于这些常量是裸字(在编译时构建)
使用此模块定义的常量不能像变量一样插入字符串。
在当前的实现(
constant
pragma)中,它们是“* 可内联子例程 *”(参见†)。这个问题可以通过使用像Const::Fast这样的模块很好地解决
现在他们得到插值。请注意,更复杂的替换可能需要
/e
。这些是在运行时构建的,因此您可以将表达式的结果分配给它们。特别地,您可以使用qr运算符,例如
qr
是构建正则表达式模式的推荐方法。(除非分隔符是'
,否则它会进行插值。)性能增益通常很小,但您可以得到一个正确的正则表达式,可以构建和使用它(在本例中也是一个常量)。我推荐使用
Const::Fast
模块,而不是另一个模块,事实上,此时所有其他模块都是如此。请参阅recent article,其中详细讨论了两者。这是一个review的许多其他选项。我强烈建议使用一个常量(你选择的类型)的东西是只读的。这对代码的健康和接触它的开发人员(包括你自己)都有好处。
†这些是子程序,我们需要能够 * 运行代码 *,以便用给定的值评估和替换它们。不能只是“插值”(计算)一个变量--它不是一个变量。
在字符串(需要插入,所以实际上是双引号)中运行代码的一种方法是解引用,其中在引用下的块中有一个表达式;则对表达式求值。因此,我们首先需要提到这一点。所以要么
或
打印
foo
。请参阅文档了解为什么这样做和示例。因此,可以在正则表达式内部以及匹配和替换部分中执行相同的操作(or与
@{[...]}
),因为它们被评估为插值字符串。哪个更好?这些都是把戏很少有,如果有的话,需要这样做。它有一个很好的机会混淆读者。所以我根本不建议诉诸这些手段。
至于
(?{ code })
,这是一个正则表达式特性,其中 * 代码在模式内部进行评估 *(仅匹配端)。它是复杂和棘手的,很少 * 需要 *。在perlretut和perlre中看到它。讨论这些事情的速度并不重要。它们肯定不在干净和惯用代码的范围之内,而您很难检测到运行时的差异。
但如果你必须使用其中之一,我宁愿通过技巧在标量引用中插值,而不是使用复杂的正则表达式特性。
不是HASH引用
在极少数情况下,解决方案
${\FOO}
需要额外的调整,例如${\FOO}{6,20}
:Perl抱怨道
不是HASH引用...
修复方法是添加额外的集群,如下所示:
(?:${\FOO}){6,20}
gjmwrych3#
根据PerlMonk的说法,如果你关心性能,你最好创建一个已经插值的字符串:
这里是whole discussion的链接。
avwztpqn4#
信用:https://www.perlmonks.org/?node_id=293323