O e
do comando s
da implementação GNU de sed
é para avaliar o conteúdo do espaço padrão após a substituição ter sido aplicada (com sucesso), e substituir o espaço do padrão com sua saída, não para avaliar a substituição .
Aqui, para uma entrada como:
foo 1234 123
Você precisaria da substituição para resultar no espaço padrão contendo:
printf %s 'foo '
printf 0x%x 1234
printf %s ' 123'
Para o sinalizador e
converter isso em foo 0x3d2 123
via o comando shell. Isso não é impossível como com:
LC_ALL=C sed -E "
/[0-9]{4}/!b # optimisation
s/'/&\\&/g
s/[0-9]{4,}/'\nprintf 0x%x &\nprintf %s '/g
s/.*/printf %s '&'/e"
Mas isso é bastante complicado e significa executar um shell por linha de entrada correspondente. Sem mesmo usar esse GNU, você poderia fazer:
LC_ALL=C sed "
s/'/&\\&/g
s/[0-9]\{4,\}/'\
printf 0x%x &\
printf %s '/g
s/.*/printf %s '&\
'/" | sh
Qual seria um sh
.
Além disso, avaliar dados arbitrários como códigos de shell como esse tendem a me deixar nervoso. Por exemplo, sem o LC_ALL = C acima, isso constituiria uma vulnerabilidade de execução de comando arbitrária. Tente, por exemplo, algo como a saída de:
printf '00000; echo GOTCHA>&2\n'
em uma localidade UTF-8.
Aqui, você prefere usar algo como perl
:
perl -pe 's/\d{4,}/sprintf "0x%x", $&/ge'
<%>
perl
e
% bandeira é mais inline com o que você espera. Ele avalia a subsituição como
perl
code (e não está lançando um novo interpretador perl sempre como no GNU
sed
'
e
).