ObiHill
ObiHill

Reputation: 11876

Strange behaviour with command-line perl

I have a file that I'm trying to modify using perl from the terminal in Ubuntu Linux (Natty).

The name of the file is vm.args and the first two lines are as follows:

## Name of the riak node
-name [email protected]

I am trying to use perl to update the ip address. Below is my code:

riak_ip=`ifconfig eth1 | grep "inet addr" | cut -d ":" -f2 | cut -d " " -f1`
perl -0777 -i -pe "s/(\-name[\t ]*riak\@)[^\n]+/\1$riak_ip/g" vm.args

Let's assume the ip address I get is 10.181.106.32. The perl command gives me a result I can't understand. The resulting first two lines in the my file after I run the above in the terminal become:

## Name of the riak node
H.181.106.32

Which is the letter H and part of the ip address.

I can't seem to figure out what I'm doing wrong and will appreciate some assistance.

Thanks in advance.

Upvotes: 1

Views: 194

Answers (5)

TLP
TLP

Reputation: 67900

Sounds like a good use for the \K sequence (v5.10). And [^\n] is actually ., unless the /s modifier is used. No need for /g option unless you intend to replace the string several times.

perl -0777 -i -pe "s/\-name[\t ]*riak\@\K.+/$riak_ip/" vm.args

Upvotes: 0

Borodin
Borodin

Reputation: 126722

This really should all be done in Perl, which is much better at extracting data from text than shell script. Something like this should work, but I cannot test it at present.

perl -0777 -i -pe '($ip)=`ifconfig eth1`=~/inet addr:([\d.]+)/;s/-name\s+riak@\K[\d.]+/$ip/g;' vm.args

I would be grateful if someone could confirm whether this works OK. Beware that the \K construct in Perl regexes is a recent addition and may not be in any given installation of Perl.

Upvotes: 1

Daniel Roethlisberger
Daniel Roethlisberger

Reputation: 7058

Problem is that \1 gets concatenated with the first IP octet. To make it work despite concatenation, the ${1} syntax needs to be used and properly quoted. This works:

perl -0777 -i -pe "s/(\-name[\t ]*riak\@)[^\n]+/\${1}$riak_ip/g" vm.args

You might consider to use single quotes for the regex parts, to remove one layer of quoting:

perl -0777 -i -pe 's/(-name[\t ]*riak@)[^\n]+/${1}'"$riak_ip"'/g' vm.args

(Edited/corrected according to comments, my previous suggestion was wrong.)

Upvotes: 0

D.Shawley
D.Shawley

Reputation: 59553

This seems to work reliably:

perl -0777 -i -pe "s/(-name\\s*riak@).*/\${1}$riak_ip/g" vm.args

The "\\1$riak_ip" seems to cause some problems since perl was seeing it as "\1172.20.2.136" if $riak_ip was 172.20.2.136. My guess is that the back reference to "1172" was causing some weirdness. Anyway, switching to the ${1} form removes the possibility for misinterpretation (pun intended).

Upvotes: 2

Birei
Birei

Reputation: 36262

This would be the correct regexp:

perl -0777 -i -pe "s/(-name\s*riak@)\S+/$1$riak_ip/g" vm.args

Result:

## Name of the riak node
10.181.106.32

Use \s for space characters, and \S (no space character) to match the whole IP address. In the replacement string, $1 is used instead \1. - and @ are not special, so there is no need to escape them, although there is nothing bad with them.

Upvotes: -1

Related Questions