Se o [
, ]
estiver balanceado e não aninhado, você poderá usar o GNU awk
como em:
gawk -v RS='[][]' '
NR % 2 == 0 {gsub(/\s/,"")}
{printf "%s", $0 RT}'
Isso é usar [
e ]
como os separadores de registro em vez do caractere de nova linha e remover espaços em branco apenas em todos os outros registros.
Com sed, com o requisito adicional de que não haja caracteres de nova linha dentro de [...]
:
sed -e :1 -e 's/\(\[[^]]*\)[[:space:]]//g;t1'
Se eles são balanceados, mas podem ser aninhados como em blah [blih [1] bluh] asd
, então você pode usar os operadores de expressão regular de recursão de perl
como:
perl -0777 -pe 's{(\[((?:(?>[^][]+)|(?1))*)\])}{$&=~s/\s//rsg}gse'
Outra abordagem, que seria dimensionada para arquivos muito grandes, seria usar o operador% regexp (?{...})
perl para acompanhar a profundidade do colchete, como em:
perl -pe 'BEGIN{$/=92}s{((?:\[(?{$l++})|\](?{$l--})|[^][\s]+)*)(\s+)}
{"$1".($l>0?"":$2)}gse'
Na verdade, você também pode processar a entrada de um caractere de cada vez, como:
perl -pe 'BEGIN{$/=}if($l>0&&/\s/){$_=""}elsif($_ eq"["){$l++}elsif($_ eq"]"){$l--}'
Essa abordagem pode ser implementada com ferramentas POSIX:
od -A n -vt u1 |
tr -cs 0-9 '[\n*]' |
awk 'BEGIN{b[32]=""; b[10]=""; b[12]=""} # add more for every blank
!NF{next}; l>0 && $0 in b {next}
$0 == "91" {l++}; $0 == "93" {l--}
{printf "%c", $0}'
Com sed
(assumindo que não há nova linha dentro do [...]
):
sed -e 's/_/_u/g;:1' -e 's/\(\[[^][]*\)\[\([^][]*\)]/_o_c/g;t1' \
-e :2 -e 's/\(\[[^]]*\)[[:space:]]//g;t2' \
-e 's/_c/]/g;s/_o/[/g;s/_u/_/g'
São considerados espaço em branco acima de qualquer caractere de espaçamento horizontal (SPC, TAB) ou vertical (NL, CR, VT, FF ...) no conjunto de caracteres ASCII. Dependendo da sua localidade, outros podem ser incluídos.