sed replace command working but output is invalid - linux

└─$ sed --version
sed (GNU sed) 4.7
file "hosts":
ip1 == 10.0.0.1
ip2 == 10.0.0.100
command executed:
sudo -i sed -i 's/10.0.0.1/10.0.0.200/g' hosts
Output file :
ip1 == 10.0.0.200
ip2 == 10.0.0.20000
The change in ip2 is not expected and an invalid.
This is just a sample logic need this logic for a Cloud Automation in RPA.
The Inputs of ip are dynamic vars.

You need to escape the . and add conditions to avoid partial match:
$ sed 's/== 10\.0\.0\.1$/== 10.0.0.200/' ip.txt
ip1 == 10.0.0.200
ip2 == 10.0.0.100
$ is end of line anchor, if there can be whitespaces at the end of the line, use \s*$
Use ==\s* instead of == if whitespaces after == can vary
I'm assuming you can have only one match per line based on given sample, so g flag isn't used
If ip1, ip2 etc aren't actually part of input, use this:
$ cat ip.txt
10.0.0.1
10.0.0.100
$ sed 's/^10\.0\.0\.1$/10.0.0.200/' ip.txt
10.0.0.200
10.0.0.100

sudo -i sed -i 's/\b10\.0\.0\.1\b/10.0.0.200/g' hosts
escape the . ( . -> . ) because means every character in regex
\b to limit the search to this exact sting

You have to change your command as follow:
sed -i -e 's:10\.0\.0\.1$:10\.0\.0\.200:g' hosts

This both helped me resolve it.
i.e.
$ sudo -i sed -i 's/10.0.0.1\b/10.0.0.200/g' hosts
or
$ sudo -i sed -i 's/<\10.0.0.1\>/10.0.0.200/g' hosts
More Responses are welcome.

Related

Parsing nmap -oG output using sed

I have a logfile
...
Host: 111.222.121.123 (111.222.121.123.deploy.static.akamaitechnologies.com) Ports: 80/open/tcp//http//AkamaiGHost (Akamai's HTTP Acceleration|Mirror service)/, 443/open/tcp//ssl|http//AkamaiGHost (Akamai's HTTP Acceleration|Mirror service)/
Host: 1.2.3.4 () Ports: 80/open/tcp//http//cloudflare/, 443/open/tcp//ssl|https//cloudflare/, 2052/open/tcp//clearvisn?///, 2053/open/tcp//ssl|http//nginx/, 2082/open/tcp//infowave?///, 2083/open/tcp//ssl|http//nginx/, 2086/open/tcp//gnunet?///, 2087/open/tcp//ssl|http//nginx/, 2095/open/tcp//nbx-ser?///, 2096/open/tcp//ssl|http//nginx/, 8080/open/tcp//http-proxy//cloudflare/, 8443/open/tcp//ssl|https-alt//cloudflare/, 8880/open/tcp//cddbp-alt?///
Host: 2.3.4.5 (a104-96-1-61.deploy.static.akamaitechnologies.com) Ports: 53/open/tcp//domain//(unknown banner: 29571.61)/
...
I need to extract and convert IPs and http ports to the following format
1.2.3.4:80,443,2083
There are just two types of port fields in the logfile
80/open/tcp//http
2083/open/tcp//ssl|http
Tried to use sed but without success. I ended up with this dysfunctional command
cat ../host_ports.txt | sed -rn 's/Host: ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*?([0-9]{1,5}\/open\/tcp\/\/http|[0-9]{1,5}\/open\/tcp\/\/ssl\|http).*/\1 \2/p'
First handle the repeating ports, and next replace Host/Port to the desired format.
sed -r 's/(Ports:|,) ([0-9]*)[^,]*/\1\2/g;s/Host: ([^ ]*).*Ports:/\1:/' ../host_ports.txt
EDIT:
First I gave all ports of a line with http somewhere, now limit the result to ports with http in its description.
sed -nr 's/Ports: /, /;
s/, ([0-9]*)[^,]*http[^,]*/,\1/g;
s/,[^,]*\/[^,]*//g;
s/Host: ([^ ]*)[^,]*,/\1:/p' ../host_ports.txt
This script will do it for you, and you don't need sed :
#!/bin/bash
while read -r line; do
if echo $line | grep -q "http"; then
host=$(echo "$line" | grep -Po '(?<=^Host: )[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+')
ports=$(echo "$line" | grep -Po '[0-9]*((?=\/open\/tcp\/\/http)|(?=\/open\/tcp\/\/ssl\|http))' | tr '\n' ',')
echo "$host:${ports:0:-1}"
fi
done < ../log
The first grep will catch the IP address, with the help of Look behind. the -P is to use perl like regex, and the -o is to output only the matching string
The second regex is much like the first, but uses look after instead of look behind. It will only capture ports which are followed by /open/tcp//http or /open/tcp//ssl|http. The tr right after will replace newlines with commas.
the ${ports:0:-1} is just to eliminate the trailing comma.
Hope this helps!

Regex to match IP addresses but ignore localhost

So I have this script that does something with IPs allocated to my OS (GNU/Linux) that I get from running ifconfig. It works fine, however, I was wondering if I could filter out loopback/localhost IP (127.0.0.1) in the same regex expression [I assume every server within my cluster has said IP and I don't need to do anything with it in my script.]
What my script uses is:
ifconfig | awk '/(([0-9]{1,3}\.){3})/ {print}' |sed -e "s/.*addr\://g" -e "s/\s.*//g"
I get results like:
> ifconfig | awk '/(([0-9]{1,3}\.){3})/ {print}' |sed -e "s/.*addr\://g" -e "s/\s.*//g"
172.16.0.1
127.0.0.1
I know it might be a stupid question, but could I filter any IP that starts with 127 in my first regex?
I could try changing awk for grep, somethin like:
> ifconfig |egrep -o "addr\:(([0-9]{1,3}\.){3}[0-9]{1,3})" |sed -e "s/.*addr\://g"
but if I try to negate (?!127) at the beginning, bash will interpret it as !127 which would just throw me something from the history.
I mean, I could just run another grep at the end of the oneliner like grep -v "127.0.0.1", but I just wanted to avoid greping something already greped. Not that anything is wrong with that, just trying to know little more and be more efficient, I guess.
With only one grep without sed or awk:
# ip a|grep -oP "inet \K[0-9.]*(?=.*[^ ][^l][^o]$)"
192.168.1.31
172.16.5.31
You can just add a clause to match the 127.0.0.1 and exclude it by adding the next as below. This way Awk ignores doing any action on the lines containing this pattern.
.. | awk '/127.0.0.1/{next}/(([0-9]{1,3}\.){3})/{print}' | ..

Reverse IP address format with sed

I have a txt file with a list of ip addresses against domain names. eg;
1.1.168.192 example1.example1.net
2.1.168.192 example2.example2.net
3.1.168.192 example3.example3.net
.....
12.1.168.192 example12.example12.net
I can't get my sed command to change the output to;
192.168.1.1 example1.example1.net
192.168.1.2 example2.example2.net
192.168.1.3 example3.example3.net
....
192.168.1.12 example12.example12.net
sed command i'm using is
sed -r 's/^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/\4.\3.\2.\1/'
using it as
cat filename | sed -r 's/^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/\4.\3.\2.\1/'
The only problem is that you've included an anchor $ in your pattern, which tries to match the end of each line but fails. You just need to remove it:
$ sed -r 's/^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/\4.\3.\2.\1/' file
192.168.1.1 example1.example1.net
192.168.1.2 example2.example2.net
192.168.1.3 example3.example3.net
Note that I'm passing the file name as an argument to sed, thereby avoiding a useless use of cat.
awk version
awk '{split(".",i,$1);printf "%d.%d.%d.%d %s\n",i[4],i[3],i[2],i[1],$2}' YourFile
$ sed -r 's/([^.]+)(\.[^.]+)(\.[^.]+)\.([^ ]+)/\4\3\2.\1/' file
192.168.1.1 example1.example1.net
192.168.1.2 example2.example2.net
192.168.1.3 example3.example3.net
192.168.1.12 example12.example12.net

Linux shell replace content in file

guys.
There is a file named 'server.conf' and I want to use shell to change content from it.
In line 115, there is server-bridge 192.168.50.225(ip) 255.255.0.0(mask) 192.168.10.50(begin ip) 192.168.10.90(end ip)
in it. I want to change the ip, mask, begin ip and end ip. For example, I plan to change
`server-bridge 192.168.50.225 255.255.0.0 192.168.10.50 192.168.10.90`
into
`server-bridge 192.168.10.100 255.255.0.0 192.168.10.60 192.168.10.80`
What should I do with sed or others tools? Thanks a lot.
sed -i 's/server-bridge\ 192.168.50.225\ 255.255.0.0\ \ 192.168.10.50\ 192.168.10.90/server-bridge\ 192.168.10.100\ 255.255.0.0\ \ 192.168.10.60\ 192.168.10.80/' server.conf
You can also create a simple script where new values to be replaced are stored in $ip ..etc.... sed -i will do in place editing to the file.
The best tool I have used is Vi.
(sudo) vi /home/mydoc.txt will open and allow you to do any editing you need done. If you have never used Vi before, there are some great HOW-TO's and tutorials online. Here is one:
http://www.howtogeek.com/102468/a-beginners-guide-to-editing-text-files-with-vi/
But I'd encourage you to really read and experiment on test files before you change the file you are referencing, AND, PLEASE, make a backup up the file ( cp /home/mydoc.txt mydoc.txt-orig ) before you do. You can always remove the edited file that does not work, but restoring the original after extensive exiting can be a hair-pulling experience.
you can use sed to do this for example some thing like this
Note:every space is escaped by \ sed Intro
cat server.conf | sed 's/server-bridge\ 192.168.50.225\ 255.255.0.0\ \ 192.168.10.50\ 192.168.10.90/server-bridge\ 192.168.10.100 255.255.0.0\ \ 192.168.10.60\ 192.168.10.80/' > server.conf
or you can use two files for safety like this
cat server.conf | sed 's/server-bridge\ 192.168.50.225\ 255.255.0.0\ \ 192.168.10.50\ 192.168.10.90/server-bridge\ 192.168.10.100 255.255.0.0\ \ 192.168.10.60\ 192.168.10.80/' > server.conf.bak
cat server.conf.bak > server.conf
You can use this awk:
awk -v ip='192.168.10.100' -v mask='255.255.0.0' -v bip='192.168.10.60' \
-v eip='192.168.10.80' '/server-bridge/{$2=ip "(ip)"; $3=mask "(mask)"; $4=bip "(begin";
$6=eip "(end"} 1' server.conf
Using sed to change all lines containing server-bridge:
sed -i -e '/^server-bridge/!b' \
-e 'c server-bridge 192.168.10.100 255.255.0.0 192.168.10.60 192.168.10.80' input
to change th 115th line only:
sed -i -e '115!b' \
-e 'c server-bridge 192.168.10.100 255.255.0.0 192.168.10.60 192.168.10.80' input

How to extract NFS information from mount on Linux and Solaris?

I need to extract NFS mount information using mount on Linux (RHEL 4/5) and Solaris (Solaris 10) systems. As this is part of an SSH command, the extraction needs to happen in one line. Unfortunately, Linux and Solaris display the mountpoint at different parts of the line:
Linux:
10.0.0.1:/remote/export on /local/mountpoint otherstuff
Solaris:
/local/mountpoint on 10.0.0.1:/remote/export otherstuff
I would like to get the following space separated output
10.0.0.1 /remote/export /local/mountpoint
I managed to do it separately with sed (Solaris 10 sed), but I need one command returing the same output for both.
Linux sed:
sed 's/\([^:]*\):\([^ ]*\)[^\/]*\([^ ]*\) .*/\1 \2 \3/'
Solaris sed:
sed 's/\([^ ]*\) *on *\([^:]*\):\([^ ]*\) .*/\2 \3 \1/'
Solution:
I adapted the accepted answer to also work with DNS names and not only IPs:
awk -F'[: ]' '{if(/^\//)print $3,$4,$1;else print $1,$2,$4}'
awk could help you:
awk -F'[: ]' '{if(/^[0-9]/)print $1,$2,$4;else print $3,$4,$1}'
see this test:
kent$ cat f
10.0.0.1:/remote/export on /local/mountpoint otherstuff
/local/mountpoint on 10.0.0.1:/remote/export otherstuff
kent$ awk -F'[: ]' '{if(/^[0-9]/)print $1,$2,$4;else print $3,$4,$1}' f
10.0.0.1 /remote/export /local/mountpoint
10.0.0.1 /remote/export /local/mountpoint
A some shoter version of Kents solution
awk -F'[: ]' '{print /^[0-9]/?$1" "$2" "$4:$3" "$4" "$1}' file
10.0.0.1 /remote/export /local/mountpoint
10.0.0.1 /remote/export /local/mountpoint

Resources