【问题标题】:Why is this regex from a text file not working with smartmatch?为什么文本文件中的这个正则表达式不能与 smartmatch 一起使用?
【发布时间】:2018-03-04 05:34:55
【问题描述】:

我用 smartmatch 检查字符串是否与正则表达式模式匹配。在我决定将正则表达式存储在文本文件中后,它就停止工作了。

my $str   = '123456, some text.';
my $regex = qr/^\d+, some text\.$/;
print "Regex: $regex\n";

此时,打印的正则表达式为(?^:^\d+, some text\.$)。我将它复制粘贴到一个文件中,然后让代码读取文件并检索存储在$regexFromFile 中的正则表达式。

以下行确认$regex$regexFromFile 相同,然后我继续以各种方式针对正则表达式测试$str

print 'Is regex equal to regexFromFile? ' . ($regex eq $regexFromFile) . "\n";

print 'Does str match regex         using =~ ? ' . ($str =~ $regex)         . "\n";
print 'Does str match regexFromFile using =~ ? ' . ($str =~ $regexFromFile) . "\n";
print 'Does str match regex         using ~~ ? ' . ($str ~~ $regex)         . "\n";
print 'Does str match regexFromFile using ~~ ? ' . ($str ~~ $regexFromFile) . "\n";

该代码的最后一行与前三行不同。

这是代码的完整输出:

Regex: (?^:^\d+, some text\.$)
Is regex equal to regexFromFile? 1
Does str match regex         using =~ ? 1
Does str match regexFromFile using =~ ? 1
Does str match regex         using ~~ ? 1
Does str match regexFromFile using ~~ ? 

(注意最后没有1。)

编辑:要回答评论,这里是文件的读取方式。

open(my $FILEHANDLE, 'file.txt') or die "Error: Could not open file.\n";
my @content = <$FILEHANDLE>;
close($FILEHANDLE) or print "Could not close file.\n";
my @content_woEol = ();
foreach my $line (@content){
    $line =~ s/\s*$//;
    push(@content_woEol, $line);
}
my $regexFromFile = $content_woEol[0];

【问题讨论】:

  • 你能展示你如何检索$regexFromFile吗?
  • 更糟糕的是,已知 smartmatch 已损坏。 问为什么损坏的代码会这样是没有用的。

标签: regex perl smartmatch


【解决方案1】:

智能匹配已损坏。请避免使用它。[1]

$str是字符串,$regexFromFile是字符串,所以$str ~~ $regexFromFile等价于$str eq $regexFromFile

如果您希望$str ~~ $regexFromFile 等同于$str =~ $regexFromFile,则必须将错误命名的$regexFromFile 从字符串转换为正则表达式(例如使用qr//)。当然,更好的解决方案是简单地使用=~


  1. 许多年前,它作为一种弃用形式进行了实验,因此可以修复。继续使用这个损坏的功能实际上阻止了最近的修复工作。

【讨论】:

  • 谁在反对任何关于 smartmatching 的负面评价?从 Perl v5.10 开始,这是一个坏主意,perldelta v5.10.1 开始倒退,~~ 变得不可交换,同时考虑了范围运算符。它总是一团糟,希望和想象力压倒了实用主义。它从来都不是 Perlish,而且它已经存活了太久。
  • 我的意思是$str ~~ $regexFromFile$str ~~ $regex 不一样,尽管$regexFromFile eq $regex 是真的...
  • $regexFromFile eq $regex 比较其操作数的字符串化,因此$regexFromFile eq $regex 为真仅表示$str ~~ "$regexFromFile"(假)和$str ~~ "$regex"(假)应该相同。
【解决方案2】:

qr// 的结果实际上是一个预编译的正则表达式。正如您所做的那样,将打印的正则表达式复制粘贴到文件中,然后从文件中读取它,这不是问题。如果您直接在代码中编写此行,您会遇到相同的行为:

my $regexFromFile = '(?^:^\d+, some text\.$)';

如果您想在这里使用 smatmatch,我建议您执行以下操作:

my $str   = '123456, some text.';
my $regex = '^\d+, some text\.$';

# Manually store this in the file: ^\d+, some text\.$
# Read $regexFromFile from the file

print 'Does str match regex         using =~ ? ' . ($str =~ /$regex/)         . "\n";
print 'Does str match regexFromFile using =~ ? ' . ($str =~ /$regexFromFile/) . "\n";
print 'Does str match regex         using ~~ ? ' . ($str ~~ /$regex/)         . "\n";
print 'Does str match regexFromFile using ~~ ? ' . ($str ~~ /$regexFromFile/) . "\n";

注意额外的/.../。输出:

Does str match regex         using =~ ? 1
Does str match regexFromFile using =~ ? 1
Does str match regex         using ~~ ? 1
Does str match regexFromFile using ~~ ? 1

【讨论】:

    【解决方案3】:

    Smartmatch 自 v5.18 以来一直是实验性,不应该在现场制作软件中使用

    一直需要

    use feature 'switch';
    

    除非你是有意或明确地忽略警告的人,否则

    no warnings qw/ experimental::smartmatch /;
    

    那么你就会对它的消亡有充分的警告

    你做了一个明智的选择,从一开始就明显错误

    【讨论】:

    • @amon:你的评论让人们感到困惑。我的帖子说“Smartmatch 自 v5.18 以来一直处于试验阶段”
    猜你喜欢
    • 2011-09-17
    • 1970-01-01
    • 1970-01-01
    • 2014-02-04
    • 2013-12-05
    相关资源
    最近更新 更多