perseusraz
perseusraz

Reputation: 89

Bash find and replace in a file isn't working, what am I doing wrong?

I'm trying to replace all of the IP addresses (except 127.0.0.1) in a file ("/etc/hosts") with a different IP that is defined earlier as a variable (n). Here is what I have:

grep -v '127.0.0.1' /etc/hosts | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | xargs -0 sed -i '$n'

If it helps, the default assignment for the variable is 192.168.2.62.

I'm a little bit of a newb, so whatever insight you have would be great, thanks!

Upvotes: 0

Views: 94

Answers (4)

Alejandro
Alejandro

Reputation: 1216

This worked for me on OSX:

find /etc/hosts -type f -exec sed -i '' '/^127\.0\.0\.1/! s/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/192.192.192.192/g' {} \;

For Linux the following should work:

find /etc/hosts -type f -exec sed -i '/^127\.0\.0\.1/! s/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/192.192.192.192/g' {} \;

Not sure if you need extra slashes before curly braces in Linux.

/^127\.0\.0\.1/! = Only do replacement on lines not starting with 127.0.0.1

Upvotes: 0

hek2mgl
hek2mgl

Reputation: 158110

You can use a single sed command for that:

sed -r '/127.0.0.1/!{s/([0-9]{1,3}\.){3}[0-9]{1,3}/'"$n"'/}' file.txt

Explanation:

/127.0.0.1/                    Regex pattern
!                              The following block gets executed if 
                               the  previous regex does not match
{                              Start of block
s                              Start of `substitute` command
/([0-9]{1,3}\.){3}[0-9]{1,3}/  Regex pattern to match an ip 
                               (simplified!)
/'"$n"'/                       Replacement IP. Interpolation of $n
}                              End of block

If you are sure the commands works as expected add the -i option. With the -i option sed will modify the original file (file.txt)

Upvotes: 2

Avinash Raj
Avinash Raj

Reputation: 174796

You could try the below Perl one-liner.

$ n="192.168.2.62"
$ echo '192.1.1.6 127.0.0.1 173.75.3.5' | perl -pe 's/\b(?!127\.0\.0\.1)[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\b/'"$n/g"
192.168.2.62 127.0.0.1 192.168.2.62

Add inline edit -i parameter to save the changes made.

Upvotes: 2

anubhava
anubhava

Reputation: 785631

You can use this awk command instead of all piped commands:

awk -v n="$n" 'NF>1 && $1 != "127.0.0.1" && $1 ~ /^\d{1,3}\./ {$1=n} 1' /etc/hosts

Upvotes: 0

Related Questions