Please consider the script below, I want to match $b to $a even if $b is a partial match. Can this done be done?
$a="MCF-7";
$b="MCF";
if($b=~m/$a/i)
{
print "FOUND";
}
While regular expressions can do this, it sounds like your problem could also be solved with the index
function:
say index($haystack, $needle) >= 0 ? 'match' : 'fail'; # any position
say index($haystack, $needle) == 0 ? 'match' : 'fail'; # anchored at start
The index
function is case sensitive. If you want an insensitive match, apply the uc
or lc
function to both arguments.
Although the index
function will be much faster than a regex, if you do want a regex solution you can build a regex generator that produces a series of alternations that will perform partial matching.
sub build_partial {
my ($str, $min) = (@_, 1);
my @re;
for (0 .. length($str) - $min) {
my $str = substr $str, $_;
for ($min .. length $str) {
push @re, quotemeta substr $str, 0, $_
}
}
my $re = join '|' => sort {length $a <=> length $b} @re;
qr/^(?:$re)$/i
}
my $haystack = 'MCF-7';
my $needle = 'MCF';
my $regex = build_partial $haystack;
say $needle =~ /$regex/ ? 'match' : 'fail'; # match
The regex generated for MCF-7
looks like this:
/^(?:M|C|F|7|MC|CF|\-|MCF|F\-|\-7|CF\-|F\-7|MCF\-|CF\-7|MCF\-7)$/i
And it will match even if the needle is a single character from the haystack. build_partial
takes an optional number indicating the minimum length required for a match:
my $regex_3 = build_partial $haystack, 3;
which produces this regex:
/^(?:MCF|CF\-|F\-7|MCF\-|CF\-7|MCF\-7)$/i
These patterns match a substring starting from any position. If you want it anchored to the front of the string, build_partial
gets a bit simpler:
sub build_partial {
my ($str, $min) = (@_, 1);
my $re = join '|' => map {
quotemeta substr $str, 0, $_
} $min .. length $str;
qr/^(?:$re)$/i
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With