Você pode primeiro escapar do &
quando encontrado em uma entidade e, em seguida, substituir os restantes. Como:
LC_ALL=C sed 's/_/_u/g; # use _ as an escape character. Here escape itself
s/&\([[:alpha:]][[:alnum:]]*;\)/_a/g; # replace & with _a when in entities
s/&\(#[0-9]\{1,8\};\)/_a/g; # Ӓ case
s/&\(#x[0-9a-fA-F]\{1,8\};\)/_a/g; # ꯍ case
s/&/\&/g; # now convert the non-escaped &s
s/_a/\&/g;s/_u/_/g; # restore escaped & and _'
com perl
:
perl -pe 's/&(?!#?\w{1,31};)/&/g'
Esse é um pouco mais lax do que o sed
em que consideraria como entidade XML qualquer coisa que comece com &
, um opcional #
e qualquer número (até 31) de alnums (ou sublinhados ) e ;
, enquanto o sed
seria mais explícito no que uma entidade é (como em &#blah;
não seria considerado como uma entidade). Na prática, não é provável que faça muita diferença.