Personally, if my regular expressions were approaching this level of complexity, I would just switch the whole operation to Perl. This one deals with an arbitrary number of open braces/parentheses/curly braces:
$ perl -ne '@open=/[\[({]/g; @close=/[)\]}]/g;
if($#close == $#open){s/(.+?)\.is/($1).is/} print' file
Or, more compact:
$ perl -pne 's/(.+?)\.is/($1).is/ if $#{/[\[({]/g} == $#{/[)\]}]/g}' file
Or more complete, this one can deal with cases like [}
(but still fails on cases like )(
):
$ perl -pne '@osqb=/\[/g; @csqb=/\]/g;
@ocb=/\{/g; @ccb=/\}/g;
@op=/\(/g; @cp=/\)/g;
if($#osqb == $#csqb && $#ocb==$#ccb && $#op == $#cp){
s/(.+?)\.is/($1).is/
}' file
When run on your example, this will print
(this_thing).is 24
(that).is 50
(a[23]).is == 10
(a).is true
(this_thing).is 24
this_thing.is (24
((that).is 50
(a[23].is == 10
a.is ( true
(this_thing.is 24
a{.is true
this_thing{.is 24
a[.is true
this_thing[.is 24
Explanation
perl -ne
: process the input file line by line (-n
) and run the script given by -e
.
@open=/[\[({]/g;
: find all opening glyphs and save the result in an array called @open
.
@close=/[)\]}]/g;
: as above but for closing glyphs.
if($#close == $#open)
: if the number of opening glyphs is equal to the number of closing glyphs (if, in other words there are hanging parentheses etc)...
s/(.+?)\.is/($1).is/
: ...then replace the shortest string that ends in .is
with itself enclosed within parentheses.
- The last
print
is outside the brackets and will be executed whether there was a substitution or not.