IMTheNachoMan
IMTheNachoMan

Reputation: 5821

find and replace a line OR add to the end of the file

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

Answers (4)

Jack
Jack

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

Tyl
Tyl

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

Ed Morton
Ed Morton

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

Tyl
Tyl

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

Related Questions