5

I'm trying to use some arithmetic over the matched patterns in perl command line. I'm able to do it for one match but not for all.

str="a1b2c3"
perl -pe 's/\d+/$&+1/e'  <<<"$str"
a2b2c3

I understand $& refers to the first matched digit 1 here. What do I need to do to add 1 to all the digits? Is there a variable similar to $& that represents all matched patterns? or the regex needs to be modified to match multiple digits.

For the given input, I'm expecting output something like

a2b3c4
10
str="a1b2c3"
perl -pe 's/\d+/$&+1/ge' <<<"$str"

The g flag to the substitution would make Perl apply the expression for each non-overlapping match on the input line.

Nitpick: There are actually no capture groups involved here (the original question mentioned capture groups). The Perl variable $& is the "string matched by the last successful pattern match". This is different from e.g. $1 and $2 etc. that refer to the string matched by the corresponding capture group (parenthesised expression). There are no capture groups in \d+, but you could have used s/(\d+)/$1+1/ge instead, which does use a single capture group.

There is no difference between s/(\d+)/$1+1/ge and s/\d+/$&+1/ge in terms of outcome. In this short in-line Perl script, it makes no difference whether you choose to use one or the other, but generally you'd like to avoid using $& in longer Perl programs that do many regular expression operations, at least if using an older Perl release.

From perldoc perlvar (my emphasis):

Performance issues

Traditionally in Perl, any use of any of the three variables $`, $& or $' (or their use English equivalents) anywhere in the code, caused all subsequent successful pattern matches to make a copy of the matched string, in case the code might subsequently access one of those variables. This imposed a considerable performance penalty across the whole program, so generally the use of these variables has been discouraged.

[...]

In Perl 5.20.0 a new copy-on-write system was enabled by default, which finally fixes all performance issues with these three variables, and makes them safe to use anywhere.

2

In case you're actually using the zsh shell (<<< is a non-standard operator that does come from zsh, but has been copied to a few other shells since), note that you don't need to invoke perl for that.

You can do:

set -o extendedglob # for (#m) below
printf '%s\n' ${str//(#m)<->/$((MATCH+1))}

Where

  • (#m) turns on the capturing of the whole match in $MATCH (the equivalent of perl's $&)
  • <-> matches any sequence of decimal digits (it's like <5-12> but without any bound).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.