Replace entire lines in a .conf file - bash

I have a situation where I want a bash script to replace an entire lines in a dnsmasq.conf
By default, lines are :
listen-address=192.168.42.1
dhcp-range=192.168.42.1,192.168.42.253,255.255.255.0,192.168.42.255,24h
dhcp-option=option:router,192.168.42.1
I implement :
new_ip=$1
broadcast=$2
base_ip=`echo $new_ip | cut -d"." -f1-3`
sed -i 's/^listen-address.*/listen-address=$new_ip/' /etc/dnsmasq.conf
sed -i 's/^dhcp-range.*/dhcp-range=$base_ip.1,$base_ip.254,255.255.255.0,$broadcast,24h/' /etc/dnsmasq.conf
sed -i 's/^dhcp-option.*/dhcp-option=option:router,$new_ip/' /etc/dnsmasq.conf
I am calling the bash as ./test.sh 172.24.239.40 172.24.239.255 and I obtain the following lines :
listen-address=$new_ip
dhcp-range=$base_ip.1,$base_ip.254,255.255.255.0,$broadcast,24h
dhcp-option=option:router,$new_ip
Is it possible to dissociate the parameter from text in sed command lines ?

You can use:
sed -i.bak -e "s/^listen-address.*/listen-address=$new_ip/" \
-e "s/^dhcp-range.*/dhcp-range=$base_ip.1,$base_ip.254,255.255.255.0,$broadcast,24h/" \
-e "s/^dhcp-option.*/dhcp-option=option:router,$new_ip/" /etc/dnsmasq.conf
i.e.
use of double quotes instead of single quotes to allow variables to expand
use of multiple substitute command in single sed instead of calling sed multiple times
use of -i.bak to keep original file safe with .bak extension

Use double quotes instead of single quotes when you have variables in sed:
sed -i "s/^listen-address.*/listen-address=$new_ip/" /etc/dnsmasq.conf
sed -i "s/^dhcp-range.*/dhcp-range=$base_ip.1,$base_ip.254,255.255.255.0,$broadcast,24h/" /etc/dnsmasq.conf
sed -i "s/^dhcp-option.*/dhcp-option=option:router,$new_ip/" /etc/dnsmasq.conf

Related

gsed replace by a variable $i with single quote

I have into a text file the following line :
\[Omega]BD=100;
I would like to replace with gsed the value 100 by a shell variable (zsh shell), here 600 :
I tried :
$ i=600
$ gsed 's/\[Omega]BD=.*/\[Omega]BD=\'\\"$i"\\';/' text_to_modify.txt | grep 600
but it returns me :
\[Omega]BD=\600; and not \[Omega]BD=600;
The is an additional backslash that I don't want, I wonder how could I remove this backslash. I would like to keep the two single quotes of gsed 's/.../.../'
Using sed;
i=600
$ sed "/\[Omega]/s/[[:digit:]]\+/$i/" input_file
\[Omega]BD=600;
You may use this sed command:
i=600
sed -E "s/(\\\\\[Omega]BD=).*/\1$i;/" file
\[Omega]BD=600;
We require additional escaping i.e. \\\\ to match a single \ because we are using double quotes around full sed command.
Or we can avoid you can use this combination of single and double quotes to avoid extra escaping:
sed -E 's/(\\\[Omega]BD=).*/\1'"$i;/" file

looping the sed -i to delete.

I have a file called foo.file.
In it are many things. I wanted to get rid of two lines containing
these keywords. employee.csv and instrument.csv. The sed -I flag is powerful feature in sed command. I like it to use on edit files in place.
It works just fine when I use in in command line format
sed -i '/employee.csv/d' foo.file
but when I try to loop the keywords. It does not work.
for i in employee.csv instrument.csv ;
do
sed -i '/"$i"/d' foo.file ;
done
~
for i in "employee.csv" "instrument.csv"; do
sed -i '/'"$i"'/d' foo.file;
done
You can also use regular expressions with sed:
sed -ri '/(employee|instrument).csv/d' foo.file;
Using sed to make an in-place substitution change:
for i in employee.csv instrument.csv; do
do sed -i "s/$i//g" foo.file;
done

How to use variables in 'sed' command?

Tried with following code:
revision=(revision="5.0")
sed -i "s/revision="1.0"/${revision}/g" /File-path/composite.xml)
But In the file the contents of revision="1.0" is replaced by ${revision}
Need to quote: "
sed -i "s/revision=\"1.0\"/${revision}/g" /File-path/composite.xml
Some syntax errors:
-i switch tell sed to execute infile replacement.
(...) tell bash to store an array of variables.
leading ) seem wrong.
My purpose:
revision='revision="5.0"'
sed -e "s/revision=\"[0-9.]*\"/${revision}/g" /File-path/composite.xml
or if you want file /File-path/composite.xml to be modified:
sed -e "s/revision=\"[0-9.]*\"/${revision}/g" -i /File-path/composite.xml
or even:
sed -e "s/revision=\"[0-9.]*\"/${revision}/g" -i.bak /File-path/composite.xml

sed in-place command not deleting from file in bash

I have a bash script which checks for a string pattern in file and delete entire line i same file but somehow its not deleting the line and no throwing any error .same command from command prompt deletes from file .
#array has patterns
for k in "${patternarr[#]}
do
sed -i '/$k/d' file.txt
done
sed version is >4
when this loop completes i want all lines matching string pattern in array to be deleted from file.txt
when i run sed -i '/pataern/d file.txt from command prompt then it works fine but not inside bash
Thanks in advance
Here:
sed -i '/$k/d' file.txt
The sed script is singly-quoted, which prevents shell variable expansion. It will (probably) work with
sed -i "/$k/d" file.txt
I say "probably" because what it will do depends on the contents of $k, which is just substituted into the sed code and interpreted as such. If $k contains slashes, it will break. If it comes from an untrustworthy source, you open yourself up to code injection (particularly with GNU sed, which can be made to execute shell commands).
Consider k=^/ s/^/rm -Rf \//e; #.
It is generally a bad idea to substitute shell variables into sed code (or any other code). A better way would be with GNU awk:
awk -i inplace -v pattern="$k" '!($0 ~ pattern)' file.txt
Or to just use grep -v and a temporary file.
first of all, you got an unclosed double quote around ${patternarr[#]} in your for statement.
Then your problem is that you use single quotes in the sed argument, making your shell not evaluate the $k within the quotes:
% declare -a patternarr=(foo bar fu foobar)
% for k in ${patternarr[#]}; do echo sed -i '/$k/d' file.txt; done
sed -i /$k/d file.txt
sed -i /$k/d file.txt
sed -i /$k/d file.txt
sed -i /$k/d file.txt
if you replace them with double quotes, here it goes:
% for k in ${patternarr[#]}; do echo sed -i "/$k/d" file.txt; done
sed -i /foo/d file.txt
sed -i /bar/d file.txt
sed -i /fu/d file.txt
sed -i /foobar/d file.txt
Any time you write a loop in shell just to manipulate text you have the wrong approach. This is probably closer to what you really should be doing (no surrounding loop required):
awk -v ks="${patternarr[#]}" 'BEGIN{gsub(/ /,")|(",ks); ks="("ks")} $0 !~ ks' file.txt
but there may be even better approaches still (e.g. only checking 1 field instead of the whole line, or using word boundaries, or string comparison or....) if you show us some sample input and expected output.
You need to use double quotes to interpolate shell variables inside the sed command, like:
for k in ${patternarr[#]}; do
sed -i "/$k/d" file.txt
done

Sed - replacing a string with a variable full of weird characters

I'm using sed to replace a character in a file with a variable. This variable is basically reading the contents of a file or a webpage which contains multiple hash-like strings like below, which are randomly generated:
define('AUTH_KEY', 'CVo|BO;Qt1B|+GE}+h2/yU7h=5`/wRV{>%h.b_;s%S8-p|>qpf]|/Vf#`&[g~*:&');
define('SECURE_AUTH_KEY', '{G2-<^jWRd7]2,?]6hhM^*asg.2C.+k=gf33-m+ZK_{Mt|q*<ELF4|gPjyxtTh!)');
define('LOGGED_IN_KEY', 'jSNo9Z;5d]tzZoh-QQ`{M-&~y??$R({:*m`0={67=+mF?L.e+R{;)+4}qCAAHz=C');
define('NONCE_KEY', '19Vt4=%8j/Z-&~ni0S<]9)J^~sy9dh|h9M_RX2#K0]F9+.v+[BP1d&B&}-FTKIJ,');
define('AUTH_SALT', 'jr7f?T|#Cbo]XVAo}N^ilkvD>dC-rr]5{al64|?_Hz }JG$yEi:_aU )Olp YAD+');
define('SECURE_AUTH_SALT', 'hm#Z%O!X_mr?lM|>>~r-?F%wi R($}|9R[):4^NTsj+gS[qnv}7|+0<9e-$DJjju');
define('LOGGED_IN_SALT', 'tyPHBOCkXZh_4H;G|^.&|^#JPB/f;{}y_Orj!6AH?#wovx+KKtTZ A[HMS9SZJ|N');
define('NONCE_SALT', 'Eb-/t 5D-vPV9I--8F<[^lcherGv.g+|7p6;+xP|5g6P}tup1K.vuHAQ=uWZ#}H^');
The variable is defined like so:
KEY=$(cat keyfile)
I used the following sed syntax:
sed -i "s/stringtoreplace/$KEY/" /path/to/file
I've also tried different variations, using single-quotes, quotes around the variables
sed -i "s/stringtoreplace/"$KEY"/" /path/to/file
sed -i "s/stringtoreplace/"${KEY}"/" /path/to/file
sed -i "s/stringtoreplace/'$KEY'/" /path/to/file
I think I "brute-forced" every way possible to put quotes and I don't know how to escape randomly generated characters like those. I keep getting the following error:
unterminated s command
Any suggestions on how to replace the string with the weird-hash-like variable?
sed is an excellent tool for simple substitutions on a single line but for anything else you should use awk:
awk -v key="$KEY" '{sub(/stringtoreplace/,key)}1' file
That will work no matter what characters "$KEY" contains, except for "&".
One possibility is to use bash instead of sed. That makes the substitution easy, but you'll have to emulate the -i option.
Something like this:
TMPFILE=$(mktemp)
KEY=$(cat keyfile)
while IFS= read -r LINE; do
echo "${LINE//stringtoreplace/$KEY}"
done </path/to/file >$TMPFILE
mv $TMPFILE /path/to/file
Try this:
KEY=$(cat keyfile | sed -e 's/[]\/()$*.^|[]/\\&/g')
sed -i "s/stringtoreplace/$KEY/" /path/to/file
The problem is that the $KEY variable contains slashes, which are the delimiters for your s command.
sed can do more than search and replace:
sed '/stringtoreplace/{
d
r keyfile
}' /path/to/file
I'm assuming "stringtoreplace" occurs by itself on a line.

Resources