I want to modify configuration files but without losing the option that was there before. For this I use the sed command to add and comment. I also use grep to check if the option doesn't exist, add it.
My problem comes when I pass the script that replicates the options twice.
## comentar linea
sudo sed -i 's/^secure-file-priv/#secure-file-priv/g' /etc/mysql/my.cnf
## inserta despues
sudo sed -i '/^#secure-file-priv/a secure-file-priv=/tmp/' /etc/mysql/my.cnf
## si no encuentra la linea la añade
grep -q secure-file-priv /etc/mysql/my.cnf 2> /dev/null ||
echo -e '######################### \nsecure-file-priv=/tmp/' >> /etc/mysql/my.cnf
The output if I run it twice is this:
#secure-file-priv=/tmp/ secure-file-priv=/tmp/ #secure-file-priv=/tmp/ secure-file-priv=/tmp/
I would like to know a way to do this correctly in Bash.
The original file could be:
option1=opt1 secure-file-priv=/tmp/ option2=opt2
and when passing the script the result was this
option1=opt1 #secure-file-priv=/tmp/ secure-file-priv=/tmp/newpath option2=opt2
And if it happens again, tell me the one that is not commented like this:
option1=opt1 #secure-file-priv=/tmp/ #secure-file-priv=/tmp/newpath secure-file-priv=/newpath/ option2=opt2
This would be a solution.
The first thing that is done is to look for the line where the term to be replaced is, after them, if it does not exist, more is added if it exists, it is replaced, using
sed
to change on the line where the text is and later. In the line following where the replacement was made, the new variable is inserted, leaving the previous ones commented out.file.txt
script.sh
First Run:
Second Run:
Third Run:
And so on.
To dissect ( parse ) a file, I think it
sed
's not quite a good tool because you quickly fall into regular expressions and things that are difficult to maintain.Although it is not much better, I think it
awk
can provide you with better tools, while more adjustable.What do you think of the following
sc.awk
?Which is executed with:
This does three things:
BEGIN{FS=OFS="="}
Defines
=
as field separator, both input and output.$1 == opt {print "#"$0; print $1, nuevo_valor; next}
See if the first field (the one up to the "=") matches the given parameter
opt
. If so, it prints the current line with a "#" in front of it. It then rewrites a line along with the new given value. It then calls tonext
stop processing the current line.1
This is an idiomatic way of getting you to
awk
type the current line without further ado. This is so because any certain action triggers the execution of{print $0}
, which is precisely what the current line writes.Regarding the use of
-v par="valor"
is the way to pass values to variables ofawk
.Let's see it in action given the following file:
Running the script
sc.awk
:Or in one line form:
As always, if you modify a sensitive file, make a copy: