Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl Regex Command Line Issue

Tags:

regex

bash

perl

I'm trying to use a negative lookahead in perl in command line:

echo 1.41.1 | perl -pe "s/(?![0-9]+\.[0-9]+\.)[0-9]$/2/g"

to get an incremented version that looks like this:

1.41.2

but its just returning me:

![0-9]+\.[0-9]+\.: event not found

i've tried it in regex101 (PCRE) and it works fine, so im not sure why it doesn't work here

like image 672
Allen Avatar asked Jun 19 '19 04:06

Allen


2 Answers

In Bash, ! is the "history expansion character", except when escaped with a backslash or single-quotes. (Double-quotes do not disable this; that is, history expansion is supported inside double-quotes. See Difference between single and double quotes in Bash)

So, just change your double-quotes to single-quotes:

echo 1.41.1 | perl -pe 's/(?![0-9]+\.[0-9]+\.)[0-9]$/2/g'

and voilà:

1.41.2
like image 178
ruakh Avatar answered Oct 12 '22 17:10

ruakh


If you want to "increment" a number then you can't hard-code the new value but need to capture what is there and increment that

echo "1.41.1" | perl -pe's/[0-9]+\.[0-9]+\.\K([0-9]+)/$1+1/e'

Here /e modifier makes it so that the replacement side is evaluated as code, and we can +1 the captured number, what is then substituted. The \K drops previous matches so we don't need to put them back; see "Lookaround Assertions" in Extended Patterns in perlre.

The lookarounds are sometimes just the thing you want, but they increase the regex complexity (just by being there), can be tricky to get right, and hurt efficiency. They aren't needed here.

The strange output you get is because the double quotes used around the Perl program "invite" the shell to look at what's inside whereby it interprets the ! as history expansion and runs that, as explained in ruakh's post.

like image 43
zdim Avatar answered Oct 12 '22 16:10

zdim