Here is an unusual method that avoids long and cryptic regex expressions altogether - using basic tr and sed commands.
Let's say we want to change "this" to "THIS" and "that" to "THAT" only inside brackets in the following text file:
$ cat inbetween two brackets [that and this] middle [this and that] one bracket that and that middle [this and that] no brackets that and this middle this and that three brackets [that and this] middle 1 [this and that] middle 2 [this and that]
This chain of commands does the job:
$ <inbetween tr '\n' '#' | tr '][' '\n' | sed '2~2 {s/this/THIS/g;s/that/THAT/g}'| sed '2~2s/.*/[&]/' | tr -d '\n' | tr '#' '\n' two brackets [THAT and THIS] middle [THIS and THAT] one bracket that and that middle [THIS and THAT] no brackets that and this middle this and that three brackets [THAT and THIS] middle 1 [THIS and THAT] middle 2 [THIS and THAT]
Inversely, we can edit text outside brackets, leaving bracket contents intact. To do that we change 2~2 in the first sed above to 1~2 (address of odd numbered lines) :
$ <inbetween tr '\n' '#' | tr '][' '\n' | sed '1~2 {s/this/THIS/g;s/that/THAT/g}'| sed '2~2s/.*/[&]/' | tr -d '\n' | tr '#' '\n' two brackets [that and this] middle [this and that] one bracket THAT and THAT middle [this and that] no brackets THAT and THIS middle THIS and THAT three brackets [that and this] middle 1 [this and that] middle 2 [this and that]
Explanation:
- first tr replaces linefeeds(\n) with # (or any character that does not appear in input file)
- second tr breaks up the resulting string to lines at every ] or [
- original bracket contents are now on even lines
- first sed edits even lines with sed using 2~2 as address
- second sed puts even lines back in brackets using s/.*/[&]/
- reverse the actions of the original tr commands
This works for editing text inside/outside all paired symbols such as brackets and quotes.