Reputation: 5821
Is it possible to either find and replace a line in a file OR append a string to the end if it is not there?
I know I can use this to find and replace:
sed -i -e "s/^SEARCH/LINE 1\nLINE 2/" file
I know I can append to the file like this:
cat << EOF | tee -i file1 file2
LINE 1
LINE 2
EOF
Is it possible to somehow to combine this. So if /^SEARCH.*$/
matches then replace it, if it doesn't, then append the replacement to the end of the file.
Update with a better input/output example:
For example, if I had this input file testfile
:
Alpha
Bravo
Charlie
Let's say I wanted to find and replace Bravo
with Bravo=bingo
, OR add Bravo=bingo
if Bravo
is not there, the expected output is:
Alpha
Bravo=bingo
Charlie
This is because Bravo
exists in the file, so it is replaced.
Let's say I wanted to find and replace Delta
with Delta=bingo
, OR add Delta=bingo
if Delta
is not there, the expected output is:
Alpha
Bravo
Charlie
Delta=bingo
This is because Delta
is not in the file so it is appended.
Upvotes: 0
Views: 693
Reputation: 6168
Don't know about a single sed
command, but you can just have sed
backup the file, then test the difference. If there is no difference, append to end of file:
sed -i.bak -e 's/^SEARCH/LINE 1\nLINE 2/' file
diff file file.bak > /dev/null
if [ $? -eq 0 ]; then
sed -i -e '$aLINE 1\nLINE 2' file
fi
Upvotes: 0
Reputation: 5252
awk one-liner:
awk 'gsub(/^SEARCH/,"LINE 1\nLINE 2"){s=1}END{if(!s)print "LINE 1\nLINE 2"}1' file
This does not replace in-place though, if you want in-place change:
awk 'gsub(/^SEARCH/,"LINE 1\nLINE 2"){s=1}END{if(!s)print "LINE 1\nLINE 2"}1' file | tee file
Remember to escape the orginal and replacement if they contain regex
characters, it's easier than change to match/substr method when the texts are not long.
Upvotes: 1
Reputation: 204015
The replacement part is exactly the same as at https://stackoverflow.com/a/54504046/1745001 but here it is simplified for this specific use case and the tweak of appending if not found is done just by setting a flag if it's found and printing at the END if that flag isn't set:
awk 'BEGIN{new="LINE 1\nLINE 2"} /^SEARCH/{$0=new; f=1} {print} END{if (!f) print new}' file
Again the above is using strings for the replacement and so will work for any chars, the /^SEARCH/
is a regexp since you don't appear to have regexp metachars but if you did you'd change that to index($0,"SEARCH")==1
or similar to do a string rather than regexp match.
Upvotes: 2
Reputation: 5252
GNU sed one-liner:
sed -i 's/^SEARCH/LINE 1\nLINE 2/;ts;bt;:s;h;:t;${x;/./!{x;s/$/\nLINE 1\nLINE 2/;be};x};:e' file
Upvotes: 0