Reputation: 1098
I use smartmatch to check whether a string matches a regex pattern. It stopped working after I decided to store the regex in a text file.
my $str = '123456, some text.';
my $regex = qr/^\d+, some text\.$/;
print "Regex: $regex\n";
At this point, the printed regex is (?^:^\d+, some text\.$)
. I copy-paste it into a file, then I make the code read the file and retrieve the regex, which is stored in $regexFromFile
.
The following line confirms that $regex
and $regexFromFile
are the same, then I proceed to test $str
against the regex in various ways.
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";
The last line of that code does not behave the same as the previous three lines.
Here is the complete output of the code:
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 ~~ ?
(Note the absence of 1
at the end.)
Edit: To answer a comment, here is how the file is read.
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];
Upvotes: 0
Views: 142
Reputation: 385887
Smartmatching is broken. Please avoid using it.[1]
$str
is a string, and $regexFromFile
is a string, so $str ~~ $regexFromFile
is equivalent to $str eq $regexFromFile
.
If you wanted $str ~~ $regexFromFile
to be equivalent to $str =~ $regexFromFile
, you'd have to convert the misnamed $regexFromFile
from a string into a regex (e.g. using qr//
). Of course, the far better solution is to simply use =~
.
Upvotes: 4
Reputation: 190
The result of qr//
is actually a precompiled regular expression. Copy-pasting the printed regular expression to a file, as you did, then reading it from the file, is not the problem. You would experience the same behavior had you written this line directly in your code:
my $regexFromFile = '(?^:^\d+, some text\.$)';
If you want to use smatmatch here, I would advise you to do something like the following:
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";
Note the additional /.../
. Output:
Does str match regex using =~ ? 1
Does str match regexFromFile using =~ ? 1
Does str match regex using ~~ ? 1
Does str match regexFromFile using ~~ ? 1
Upvotes: 2
Reputation: 126722
Smartmatch has been experimental since v5.18 and should never have been used in live production software
It has always required
use feature 'switch';
And unless you are someone who consciously or explicitly ignores warnings, with
no warnings qw/ experimental::smartmatch /;
then you will have had ample warning of its demise
You have made an informed choice that was clearly wrong from the start
Upvotes: -1