我使用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];
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
智能匹配被打破了。请避免使用它。[1]
$str
是一个字符串,$regexFromFile
是一个字符串,所以$str ~~ $regexFromFile
相当于$str eq $regexFromFile
。
如果你想让$str ~~ $regexFromFile
等同于$str =~ $regexFromFile
,你必须将错误命名的$regexFromFile
从字符串转换为正则表达式(例如使用qr//
)。当然,更好的解决方案是简单地使用=~
。
Smartmatch自v5.18开始一直处于试验阶段,绝不应该用于现场制作软件
它一直都需要
use feature 'switch';
除非你是有意识或明确地忽略警告的人,否则
no warnings qw/ experimental::smartmatch /;
然后你会对它的灭亡发出充分的警告
你做出了明智的选择,从一开始就明显是错误的