Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I match text and replace it with a computed value based on the match in Perl?

Tags:

regex

perl

I have a function, call it f, that takes a string and returns a string.

I have a file with lines that look like this:

stuff:morestuff:stuff*:otherstuff:otherstuff*\n

Colons only appear as delimiters and * only appears at the end of each word. I want to loop over the file and replace all instances of stuff* with f(stuff). The previous line would go to

stuff:morestuff:f(stuff):otherstuff:f(otherstuff)\n

I can do this in a few lines, but there must be a way to do it in one.

Edit To be clear, by f(stuff), I mean f called on "stuff", not the string "f(stuff)".

like image 311
pythonic metaphor Avatar asked Dec 07 '22 04:12

pythonic metaphor


1 Answers

If you use the e option for s// then the right hand expression is evaluated as code. So this is as simple as:

$line =~ s/([^:]+)\*/f($1)/ge;

Breaking down the match:

  • ( starts marking part of the pattern
  • [^:] means anything but a :
  • + means one or more of these, i.e. one or more characters that's not a colon
  • ) ends marking part of the pattern as $1
  • \* means literally a *

This pattern is relying on the fact that * only appears at the end of each word. If it could appear in the middle of a field you'd need to tweak the pattern a little.

Or, putting the pattern in a whole script:

sub f {
    my $word = shift;
    $word =~ tr/a-z/A-Z/;
    return $word;
}

while (<>) {
    s/([^:]+)\*/f($1)/ge;
    print;
}
like image 87
Dave Webb Avatar answered Jan 05 '23 00:01

Dave Webb