sed: how to replace line if found or append to end of file if not found?
It's actually quite simple with sed
: if a line matches just copy it to the h
old space then s
ubstitute the value.
On the la$
t line ex
change hold space and pattern space then check if the latter is empty. If it's not empty, it means the substitution was already made so nothing to do. If it's empty, that means no match was found so replace the pattern space with the desired variable=value then append to the current line in the hold buffer. Finally, ex
change again:
sed '/^FOOBAR=/{h;s/=.*/=newvalue/};${x;/^$/{s//FOOBAR=newvalue/;H};x}' infile
The above is gnu sed
syntax. Portable:
sed '/^FOOBAR=/{
h
s/=.*/=newvalue/
}
${
x
/^$/{
s//FOOBAR=newvalue/
H
}
x
}' infile
Here is a simpler sed
approach, as I don't find sed
hold space
easy to work with. If you are comfortable with hold space
, using don_crissti approach gives additional opportunity to preserve anything from the existing line, but this is usually very rare.
In this approach, you just print all but the line that you want to drop and then at the end, append the replacement.
sed -n -e '/^FOOBAR=/!p' -e '$aFOOBAR=newvalue' infile
This can probably be shortened. It's not a single sed command and it also uses grep, but this seems to be basically what you're wanting. It's a single line, and it edits the file in-place (no temp files).
grep -q "^FOOBAR=" file && sed "s/^FOOBAR=.*/FOOBAR=newvalue/" -i file ||
sed "$ a\FOOBAR=newvalue" -i file
Simply use grep
and echo
to create an empty record :
grep -q '^FOOBAR=' somefile || echo 'FOOBAR=VALUE' >> somefile
sed -i 's/FOOBAR=.*$/FOOBAR=VALUE/' somefile
Each line escapes with error code zero.
Based on the other answers, if what you want to do is replace a variable's value if that variable is present in the file and append it to the end of the file if it is not (which is not what your posted sed
commands do), you could try this:
perl -ne '$c=1 if s/^FOOBAR=.*$/FOOBAR=newvalue/;
print;
END{print "FOOBAR=newvalue" unless $c==1}' file > tmpfile &&
mv tmpfile file