Por que seu comando falha:
Você fez:
sed 's/\([^\]\)&/\&/g' <<< "${text}"
-
[^\]\corresponde a qualquer caractere, exceto\, e coloca isso no grupo correspondente 1, então&corresponde a um literal&. Portanto, paraone&two\&three, isso corresponderá aeantes do primeiro&, coloque isso no grupo capturado 1. Para o&antes dethree, isso não será correspondido, pois\é antes de& -
Na substituição você usou
\&, então a saída se tornaone\e&two\&threeporque:-
é substituído pore - dois
\s são tratados como\. que nos dáe\até agora - , então
&corresponderá à correspondência completa, ou seja,e&, ou seja,&não será ignorado, como você estava pensando
-
-
Assim, a parte correspondente, por exemplo,
e&, é substituída pore\e&Você obteria o resultado desejado se estivesse usando outro
\antes de&(Como dois\fazem um\, então você precisa de um antes de&também:sed 's/\([^\]\)&/\\&/g' <<<"${text}"Como o
seddo Ubuntu suporta ERE (Expressão Regular Estendida), você pode usar a opção-Eou -rpara permitir que se livre do()s durante a captura:sed -E 's/([^\])&/\\&/g' <<<"${text}"
Abordagem alternativa:
Primeiro, remover \ s antes de todo & s e, em seguida, adicionar \ antes de todo & :
sed -E 's/[\]+(&)//g; s/&/\&/g'
Isso é composto de duas declarações sed :
-
s/[\]+(&)//gremove todos os\s antes de&na string (linha) -
s/&/\&/gadiciona\também&na string (linha)
Exemplo:
% text='one&two\&three'
% sed 's/\([^\]\)&/\\&/g' <<< "${text}"
one\&two\&three
% sed -E 's/([^\])&/\\&/g' <<< "${text}"
one\&two\&three
% sed -E 's/[\]+(&)//g; s/&/\&/g' <<<"$text"
one\&two\&three