Replace all IP addresses in a file to a specified string - bash

I have a huge list of IP address in a file and I want to replace all the IP address to a specified string( Example : X.X.X.X).
#Example.txt
1,1.1.1.1
2,10.10.10.10
3,5.5.5.5
4,6.6.6.6
.........
I tried replacing using sed
$sed -e 's/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/x.x.x.x/g' example.txt
I couldn't achieve this. Can some one help me on how to replace the IP address with a specific string?

You were almost there! All that you have to do is escape the repetition braces:
sed -e 's/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/x.x.x.x/g' test.txt

Related

Missing character in sed grouping

I am trying to get an IP from a string by using sed grouping and I can't figure out what is wrong with this.
input:
echo "instream(10.20.213.11#40266):" | sed -E 's/.*([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*/\1/'
output:
0.20.213.11
Why is the first number missing?
You can replace .* that matches greedily to a .*[^0-9] requiring a non-digit char before the subsequent digit matching regex part:
sed -E 's/.*[^0-9]([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*/\1/'
It will work since IP addresses in your string are not at the start of the string.
See the online demo:
#!/bin/bash
echo "instream(10.20.213.11#40266):" | \
sed -E 's/.*[^0-9]([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*/\1/'
# => 10.20.213.11
If your IP addresses can be at the string start, you can use
sed -E 's/(.*[^0-9]|^)([0-9]+(\.[0-9]+){3}).*/\2/'
See this online demo. Here, (.*[^0-9]|^) matches either any text up to the right-most non-digit or start of string. Now, the IP address matching pattern will land in Group 2, hence is the use of \2 in the replacement (RHS).
If your sed supports word boundaries, consider using word boundaries:
sed -E 's/.*\b([0-9]+(\.[0-9]+){3})\b.*/\1/'
See this online demo, too.

grep exact pattern from a file in bash

I have the following IP addresses in a file
3.3.3.1
3.3.3.11
3.3.3.111
I am using this file as input file to another program. In that program it will grep each IP address. But when I grep the contents I am getting some wrong outputs.
like
cat testfile | grep -o 3.3.3.1
but I am getting output like
3.3.3.1
3.3.3.1
3.3.3.1
I just want to get the exact output. How can I do that with grep?
Use the following command:
grep -owF "3.3.3.1" tesfile
-o returns the match only and not the whole line.-w greps for whole words, meaning the match must be enclosed in non word chars like <space>, <tab>, ,, ; the start or the end of the line etc. It prevents grep from matching 3.3.3.1 out of 3.3.3.111.
-F greps for fixed strings instead of patterns. This prevents the . in the IP address to be interpreted as any char, meaning grep will not match 3a3b3c1 (or something like this).
To match whole words only, use grep -ow 3.3.3.1 testfile
UPDATE: Use the solution provided by hek2mgl as it is more robust.
You may use anhcors.
grep '^3\.3\.3\.1$' file
Since by default grep uses regex, you need to escape the dots in-order to make grep to match literal dot character.

sed: replace ip in hosts file, using hostname as pattern

I'm learning about sed but it is very difficult to me understand it.
I have adsl with dynamic ip so and i want to put current ip on hosts file.
This following script just tells me the current wan ip address and no more:
IP=$(dig +short myip.opendns.com #resolver1.opendns.com)
echo $IP
The result:
192.42.7.73
So, i have a line on hosts file with the old ip address:
190.42.44.22 peep.strudel.com
and i want to update host file like this:
192.42.7.73 peep.strudel.com
How can i do it? I think i can use the hostname as pattern...
The reason of doing this is because my server is a client of my router, so it access the internet thru its gateway and not directly. And postfix always is logging me that "connect from unknown [x.x.x.x]" (where x.x.x.x is my wan ip!) and it can't resolve that ip. I think that maybe if i specify this relating with my fqdn host/domain, on hosts file it will works better.
Thanks
Sergio.
You can use a simple shell script:
#! /bin/bash
IP=$(dig +short myip.opendns.com #resolver1.opendns.com)
HOST="peep.strudel.com"
sed -i "/$HOST/ s/.*/$IP\t$HOST/g" /etc/hosts
Explanation:
sed -i "/$HOST/ s/.*/$IP\t$HOST/g" /etc/hosts means in the line which contains $HOST replace everything .* by $IP tab $HOST.
using sed
sed -r "s/^ *[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+( +peep.strudel.com)/$IP\1/"
.
[0-9]+\. find all lines that matches 1 or more digits with this pattern 4 consecutive times then pattern peep.strudel.com .The parenthesis around the pattern peep.strudel.com save it as \1 then replace the whole patten with your variable and your new ip.
another approach:instead of saving pattern to a variable named IP, you can execute your command line inside sed command line to get the new IP .
sed -r "s/^ *[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+( +peep.strudel.com)/$(dig +short myip.opendns.com #resolver1.opendns.com)\1/"
using gawk
gawk -v IP=$IP '/ *[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+( +peep.strudel.com).*/{print gensub(/ *[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+( +peep.strudel.com)/,IP"\\1","g")}'
You need to include the sed code inside double quotes so that the used variable got expanded.
sed "s/\b\([0-9]\{1,3\}\.\)\{1,3\}[0-9]\{1,3\}\b/$IP/g" file
Add -i parameter to save the changes made. In basic sed \(..\) called capturing group. \{min,max\} called range quantifier.
Example:
$ IP='192.42.7.73'
$ echo '190.42.44.22 peep.strudel.com' | sed "s/\b\([0-9]\{1,3\}\.\)\{1,3\}[0-9]\{1,3\}\b/$IP/g"
192.42.7.73 peep.strudel.com

How to change IP dynamically in hadoop conf.xml

cat test.xml |sed -r 's/(\b[0-9]{1,3}\.){3}[0-9]{1,3}\b'/$ip_address/ >new.xml
Here, I am trying to replace pattern matching IP with new IP address. I am getting
unterminated s command. Please let me know what is going wrong

sed: modify a file using contents of another file

I've got a script which writes an ip address to a file ip.txt
I want to replace an ip address in an html file with the ip from ip.txt.
I've got a sed regex expression that matches an ip address, and I want to replace this matched text with the contents of ip.txt:
"s/\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}//g"
How can I get sed to pull the contents of ip.txt and put it in the expression s/<search>/<*HERE*>/g?
Is there a better way to do it than this?
sed -e "s/\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}/"`cat ip.txt`"/g"
Not much of an improvement, but you can replace
"`cat ip.txt`"
with
$(<ip_txt)
which will be replaced with the contents of the file and is slightly more efficient than using cat.
You can read the IP into a shell variable before running the sed command. Assuming that ip.txt is a single line containing only the IP address:
read -r ip < ip.txt
sed -e "s/\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}/$ip/g" file.html > newfile.html
mv newfile.html file.html
POSIX sed (and therefore most of the available implementations of sed) supports the r file command to read a file when a line is matched. As long as you don't mind have the result containing newlines either side of where the IP address was, you could easily enough do it using r. The description says:
[1addr]r rfile
Copy the contents of rfile to standard output as described previously. If rfile does not exist or cannot be read, it shall be treated as if it were an empty file, causing no error condition.
This means that you don't get a chance to edit the contents of the file, whereas if it was read into the pattern space or hold space, you could could then modify the data.
This being the case, your command line substitution is about as good as you can do.

Resources