Issue
My file looks like this:
FooBarA
foo bar
foo = bar
FooBarB
foo bar
foo = bar
FooBarC
foo bar
foo = bar
...
What I would like to do is to write a script that replaces the bar
in foo = bar
but only if it belongs to FooBarB
. So in the example above only the second bar
out of all foo = bar
lines should be replaced.
I've played around with sed
but I just can't get it done right. I would also like to avoid installing any tools that aren't necessarily pre-installed on the system (I'm on Mac OS), since the script will be used by other team members too.
Solution
One way to do it with sed
(tested using macOS's sed and GNU sed), would be this:
replace.sed
#!/usr/bin/env sed -Ef
/FooBarB/,/^FooBar/ {
s/(foo[[:space:]]*=[[:space:]]*).+/\1new-value/
}
Here's what it does:
/FooBarB/,/^FooBar/
matches a range of lines where the first line matches the regex/FooBarB/
and the last line matches the regex/^FooBar/
(which is the start of the next "group"). The comma between the two regexes is the syntax for range matching insed
.s/(foo[[:space:]]*=[[:space:]]*).+/\1new-value/
— [s]ubstitutes (in the matched range of lines) whatever matches the regex(foo[[:space:]]*=[[:space:]]*).+
with\1new-value
, where\1
references the first capturing group in the search regex. The search regex looks forfoo
followed by optional whitespace, followed by an=
sign, followed again by whitespace and then whatever else is there, which in your case is the old value.
You could do it all in just one line, but I wanted to show a version that's a bit more digestible (as far as sed
goes, in any case):
sed -E '/FooBarA/,/^FooBar/s/(foo[[:space:]]*=[[:space:]]*).+/\1new-value/' temp.md
Answered By - IonuČ› G. Stan Answer Checked By - Mary Flores (WPSolving Volunteer)