I have a file like this
www IN A 192.168.10.1
webmail IN A 192.168.10.2
mail IN A 192.168.10.3
I want to write a bash script that get 3 input like this
./script.sh network.com www 192.168.10.10
and script is
project=$1
server=$2
ip=$3
h=$(awk -F "$server IN A" '{print $2}' /home/forward.$project)
sed -i "s/$h/$ip/"
I want to find line that start with second input and replace (ip) with third input but my script doesn't work.
You can select the line in sed and do regexp replace.
project=$1
server=${2//./\\.} # escape '.' to avoid problems with sed if $server contains some
ip=$3
sed -E "/^$server /s/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/$ip/" "$1"
Using awk:
$ echo network.com www 192.168.10.10 |
awk '
NR==FNR {
a=$2 # store hostname
b=$3 # and ip
next # .
}
$1==a { # if hostname matches
sub(/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/,b) # replace ip looking string
}1' - a_file # output
Output:
www IN A 192.168.10.10
webmail IN A 192.168.10.2
mail IN A 192.168.10.3
Edit :
A version which adds non-matching record to the end:
$ echo network.com www2 192.168.10.10 |
awk '
NR==FNR {
a=$2 # store hostname
b=$3 # and ip
next # not needed for this input but good practise
}
FNR==1 { t=$0 } # store a template record for later use
$1==a { # if hostname matches
sub(/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/,b) # replace ip looking string
f=1 # flag up when there was replace
}
1; # output
END { # in the end
if(!f) { # if there was no replace
sub(/^[^ \t]+/,a,t) # replace the template
sub(/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/,b,t)
print t # and output it
}
}' - a_file
Output:
www IN A 192.168.10.1
webmail IN A 192.168.10.2
mail IN A 192.168.10.3
www2 IN A 192.168.10.10
$ cat script.sh
#!/bin/env bash
project=$1
server=$2
ip=$3
file="file" # change to "/home/forward.$project"
awk -v server="$server" -v ip="$ip" '
$1 == server {
sub(/[^[:space:]]+[[:space:]]*$/,"")
$0 = $0 ip
found = 1
}
{ print; lastLine=$0 }
END {
if ( !found ) {
match(lastLine,/^[^[:space:]]+[[:space:]]+/)
gsub(/^[^[:space:]]+[[:space:]]+|[^[:space:]]+[[:space:]]*$/,"",lastLine)
printf "%-*s %s%s\n", RLENGTH-1, server, lastLine, ip
}
}
' "$file"
.
$ ./script.sh network.com www 192.168.10.10
www IN A 192.168.10.10
webmail IN A 192.168.10.2
mail IN A 192.168.10.3
$ ./script.sh network.com fluffy 192.168.10.10
www IN A 192.168.10.1
webmail IN A 192.168.10.2
mail IN A 192.168.10.3
fluffy IN A 192.168.10.10
$ ./script.sh network.com super_long_server 192.168.10.10
www IN A 192.168.10.1
webmail IN A 192.168.10.2
mail IN A 192.168.10.3
super_long_server IN A 192.168.10.10
The above will work portably and robustly (ie no chance of false matches or other failures due to partial matching or regexp characters or delimiters like /
appearing in the input or arguments) using any awk in any shell on any UNIX box
To write back to the original file you could add -i inplace
at the front of the awk script if you're using GNU awk, or add > tmp && mv tmp "$file"
after the end of it otherwise.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.