In case you don't have access to tools that support lookarounds, this approach though lengthy will work robustly using standard tools on any UNIX box:
awk '{
gsub(/@/,"@A"); gsub(/{/,"@B"); gsub(/}/,"@C"); gsub(/pattern1/,"{"); gsub(/pattern2/,"}")
out = ""
while( match($0,/{[^{}]*}/) ) {
out = (out=="" ? "" : out ORS) substr($0,RSTART,RLENGTH)
$0 = substr($0,RSTART+RLENGTH)
}
$0 = out
gsub(/}/,"pattern2"); gsub(/{/,"pattern1"); gsub(/}/,"@C"); gsub(/{/,"@B"); gsub(/@A/,"@")
} 1' file
The above works by creating characters that can't exist in the input (by first changing those characters {
and }
to some other strings @B
and @C
) so it can use those chars in a negated character class to find the target strings and then it returns all the changed chars to their original values. Here it is with some prints to make it more obvious what's happening at each step:
awk '{
print "1): " $0 ORS
gsub(/@/,"@A"); gsub(/{/,"@B"); gsub(/}/,"@C"); gsub(/pattern1/,"{"); gsub(/pattern2/,"}")
print "2): " $0 ORS
out = ""
while( match($0,/{[^{}]*}/) ) {
out = (out=="" ? "" : out ORS) substr($0,RSTART,RLENGTH)
$0 = substr($0,RSTART+RLENGTH)
}
$0 = out
print "3): " $0 ORS
gsub(/}/,"pattern2"); gsub(/{/,"pattern1"); gsub(/}/,"@C"); gsub(/{/,"@B"); gsub(/@A/,"@")
print "4): " $0 ORS
} 1' file
1): pattern1 this is the first content pattern2 this is some other stuff pattern1 this is the second content pattern2 this is the end of the file.
2): { this is the first content } this is some other stuff { this is the second content } this is the end of the file.
3): { this is the first content }
{ this is the second content }
4): pattern1 this is the first content pattern2
pattern1 this is the second content pattern2
pattern1 this is the first content pattern2
pattern1 this is the second content pattern2