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

2 Answers 2

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.

0
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).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .