bratwiz has asked for the wisdom of the Perl Monks concerning the following question:

I want to do this:

my $line = 'marker <this> <that> <other>'; my $rex = qr/(?:^marker\s|\G)<(.*?)>(?: |$)/g; my @matches = ($line =~ $rex);

But it doesn't work -- can't use the '/g' modifier for some reason when defining the regex !!??!

But this does work:

my @lines = ( 'notmarker <blah> <foo> <bar>', 'marker <this> <that> <other>', 'notmarker <blech> <phooey>', ); foreach (@lines) { chomp; if (my @matches = (/(?:^marker\s|\G)<(.*?)>(?: |$)/g)) { print join(', ', @matches)."\n"; } }

How can I achieve what the second example does using precompiled patterns???

I'm stumped. I'm sure there is some smart perl person here who can help !?!?

Edited by planetscape - removed pre tags, replaced with code tags

Replies are listed 'Best First'.
Re: Global Modifier on a Pattern -- HOW!?!?!?
by duff (Parson) on Mar 24, 2006 at 06:42 UTC

    The /g modifier doesn't make sense on a precompiled regular expression as it applies to the actions of the matching engine itself, not the pattern. The way to "fix" it is to use the /g at pattern application time:

    @matches = $line =~ /$rex/g;
    Or, if you really have a need to dynamicize the global aspect of a pattern match, use strings and eval rather than qr// (somehow I think this isn't what you want though)
Re: Global Modifier on a Pattern -- HOW!?!?!?
by tirwhan (Abbot) on Mar 24, 2006 at 06:42 UTC

    g is not a valid modifier for qr (see the description of qr under "Regexp Quote-Like Operators" in perldoc perlop for a list of valid modifiers). You can do what you want this way:

    my $line = 'marker <this> <that> <other>'; my $rex = qr/(?:^marker\s|\G)<(.*?)>(?: |$)/; my @matches = ($line =~ /$rex/g);

    All dogma is stupid.

      Thanks for your comments. I did read the perldocs a couple of times through before I posted and was aware of the syntax for qr(), including it not supporting the '/g' modifier.

      I guess I'm so used to there being "more than one way to do it in perl" that I was baffled when I came across a situation where there wasn't even that one :)

      I am aware that I can do it at runtime as in my example. However, what I am attempting to accomplish is to discover a method whereby I can specify a single pattern to:

      • Only extract information from a line that contains a specific marker
      • Extract multiple bits of information
      The idea being is that I have a bunch of lines, of which many (most) _are not_ the line I want (ie. they don't have the marker part) but all of them would otherwise correspond to the rest of the expression to pull out the multiple data items (see my example). For my purposes, I _only_ want to extract the multiple data items from the line that matches the marker.

      As you can see in my example, I found a way to do it with a regex, but as it turns out I cannot precompile that regex. And, as this is a snippet from a larger bit of code-- as you might have guessed, I really need for it to be able to be expressed as a single pattern string.

      However, from the nature of the replies here, I'm thinking that perhaps the best way is to encode the need for a '/g' modifier into the string (or else something related)-- and then do some quick pre-processing in my code to direct it to execute either with, or without the '/g' modifier.

      Thanks all for suggestions and comments. I love coding in perl!