Home > other >  Sed replace first instance of word in each block of text without leaving bash
Sed replace first instance of word in each block of text without leaving bash

Time:12-15

I have some text containing identifiable blocks of text stored in a variable $mytext:

start
This is my house and I can see my car from it.
This is my dog and it dislikes squirrels.
end

start
This is my car and I can see my house from it.
This is my dog and it dislikes squirrels.
end

I want to replace just the first "my" with "our" in each block from "start" to "end" so that I end up with

start
This is our house and I can see my car from it.
This is my dog and it dislikes squirrels.
end

start
This is our car and I can see my house from it.
This is my dog and it dislikes squirrels.
end

So what I've got is the following:

sed -zE "/start/, /end/ s/my/our/1;q" <<< $mytext

but this will only replace just the first "my" in the first block and ignores the "my" in the second block. I think that this is because it is finding the first "start" and the last "end" and so only doing the replace once.

Of course the text in $mytext is a much simpler version of what I'm actually trying to do but it is there to illustrate the point.

How do I replace both first instances of "my" in the two blocks without leaving bash?

CodePudding user response:

If you want to give awk a chance then use:

awk 'p==1 {p  = sub(/my/, "our")} /^start$/ {p=1} /^end$/ {p=0} 1' file

start
This is our house and I can see my car from it.
This is my dog and it dislikes squirrels.
end

start
This is our car and I can see my house from it.
This is my dog and it dislikes squirrels.
end

CodePudding user response:

With sed first replace the my string by an unique character.
Next a "normal" sed command where you you replace the first unique character after start.
And now restore the remaining temp characters with the original value.

sed -zE 's/ my /\r/g;s/(start[^\r]*)\r/\1 our /g;s/\r/ my /g' file
  • Related