so860
so860

Reputation: 438

sed: replace first instance only with string containing bash variable

This is a bit of a follow-on from How to use sed to replace only the first occurrence in a file? but with a more targeted ask. Given a file

Peach: data/file1.txt
Apple: data/file2.txt
Pear: data/file3.txt
Apple: data/file4.txt

The goal is to replace only the first line containing Apple with a new line containing a fixed string (Banana) followed by a bash variable. In the new output, line 2 is now:

Banana: newdata/data.txt

Here is the most recent attempt...

BananaVariable=newdata
sed -i -E "0,|(Apple).*|{s|(Apple:).*|Banana: "$BananaVariable"/data.txt|}" filename

However, this produces the error:

sed: -e expression #1, char 3: unexpected  `,'

I think I need the double quotes around $BananaVariable to escape so that it can insert the actual string rather than "BananaVariable", but I think those double quotes are causing the problem. (OS is CentOS 7, sed is GNU version)

Upvotes: 0

Views: 2333

Answers (3)

builder-7000
builder-7000

Reputation: 7627

From man sed:

/regexp/
       Match lines matching the regular expression regexp.

\cregexpc
       Match  lines  matching the regular expression regexp.  The c may
       be any character.

So in your original command replace the first two bars | with slash / (equivalently, replace the first | with \|):

sed -i -E "0,/(Apple).*/{s|(Apple:).*|Banana: $BananaVariable/data.txt|}" filename

You can also shorten the command:

sed -i -E "0,/^Apple/s|.*|Banana: $BananaVariable/data.txt|" filename

output:

Peach: data/file1.txt
Banana: newdata/data.txt
Pear: data/file3.txt
Apple: data/file4.txt

Upvotes: 1

potong
potong

Reputation: 58440

This might work for you (GNU sed):

sed -i -e '0,/Apple/!b;//cBanana: '"$BananaVariable"'/data.txt' file

If a line is not between the front of the file until a line containing Apple print as normal. Otherwise change the line containing Apple to the required string using a variable.

Upvotes: 0

anubhava
anubhava

Reputation: 785276

It is easier with awk:

var='newdata/data.txt'
awk -v v="$var" 'BEGIN{FS=OFS=": "}
!p && $1 == "Apple"{$1="Banana"; $2=v; p=1} 1' file

Peach: data/file1.txt
Banana: newdata/data.txt
Pear: data/file3.txt
Apple: data/file4.txt

Upvotes: 0

Related Questions