yonyon100 yonyon100 - 3 months ago 10
Perl Question

Pre-compiled regex with special characters matching

I'm trying to match if a word such as

*FOO
(* as a normal character) is in a line. My input is a C++ source code. I need to use a pre-compiled regex for this due to program flow requirements, so I tried the following:

$pattern = qr/[^a-zA-Z](\*FOO)[^a-zA-Z]|^\s*(\*FOO)[^a-zA-Z]/;


And I use it like this:

if ($line =~ m/$pattern/) { ... }


It works and catches lines containing
*FOO
such as
hey *FOO.BAR
but also matches lines such as:

//FOO programming using stuff and things


which I want to ignore. What am I missing? Is
\*
not the right way to escape
*
in a pre-compiled regex in perl? If
*FOO
is stored in
$word
and the pattern looks like this:

$pattern = qr/[^a-zA-Z](\\$word)[^a-zA-Z]|^\s*(\\$word)[^a-zA-Z]/;


Is that different from the previous pattern? Because I tried both and the result seems to be the same.

I found a way to bypass this problem by removing the first char of
$word
and escaping
*
in the pattern, but if
$word = "**.?FOO"
for example, how do I create a
qr//
with
$word
so that all the meta-characters are escaped?

Answer

You do need to escape the *. One way to do it is by quotemeta

use warnings;
use strict;

my $qr = /\Q*FOO/;

while (<DATA>) { print if /$qr/ }

__DATA__
//FOO programming using stuff and things
hey *FOO.BAR

This determines whether *FOO is in the line, regardless of whether it is a word or a part of a word. It is not clear to me from the question which is the case. Once that is specified the pattern can be adjusted.

Note that /\*FOO/ works, too. What you tried failed probably because of all the rest that you are trying to match, which purpose I do not understand. If you only need to detect whether the pattern is present the above does it. if there is a more specific requirement please clarify.

Comments