Não consigo ver como isso pode ser feito com apenas sed, já que as expressões regulares normais não devem ser capaz de corresponder parênteses aninhados . Felizmente, coisas como o Perl também suportam expressões não tão regulares, como este roubado da resposta aqui :
echo "out side (in ( side ( ) ) remove ( spaces ) ) out ( in again )." |
perl -lpe 's/\(([^()]|(?R))*\)/ local $_ = $&; s,\s+,,g; $_ /eg'
out side (in(side())remove(spaces)) out (inagain).
A expressão (não) regular funciona da seguinte maneira:
\(([^()]+|(?R))*\)
^^| | ||^^ -- literal parenthesis, inside of which:
^ ^ ^| --- group with choice:
^^^^^^ ^^^^ | ---- anything except parenthesis, any number,
| OR this whole pattern again.
^ ----- any number of those two choices
A peça de substituição pega a string correspondente de $&
, modifica-a em uma variável local, remove todos os caracteres de espaço em branco e retorna o valor modificado. ( s///
não funciona em $&
ou $1
diretamente).
Embora seja mais fácil saber se você tem apenas um parêntese em uma única linha, pode corresponder do primeiro (
ao último )
.
echo "out (in ( side) here ) out again." |
perl -pe 's/\(.*\)/ $_ = $&; s,\s+,,g; $_ /e'
out (in(side)here) out again.
Isenção de responsabilidade: não sei se usar $_
dentro do s///e
pode quebrar, mas parece funcionar para mim.