Como observado, o shell provavelmente não é o melhor lugar para fazer isso. Se você realmente quiser, aqui está uma solução usando awk , dc , printf , sed e tr :
#!/bin/sh
# file: swap-bits
target_order='D5679123C4EF80AB'
indices() {
printf '%s\n' "$1" \
| sed 's/./$ echo B455 | ./swap-bits
CB15
1+p\n/g' \
| sed '1s/^/10o16i/' \
| dc \
| sed 's/^/substr( $0, /' \
| sed 's/$/, 1 )/' \
| tr '\n' ' '
echo
}
sed 's/^/2o16iF/' \
| sed 's/$/p/' \
| dc \
| sed 's/....//' \
| awk "{ print \"16o2i\" $(indices ${target_order}) \"pq\" }" \
| dc \
| sed 's/^/0000/' \
| sed 's/.*\(....\)$//'
Isso não faz verificação da entrada.
A variável target_order deve ser configurada para a permutação preferencial dos seus 16 bits.
A função indices toma como entrada uma string e produz uma seqüência de comandos substr( $0, n, 1 ) , que awk usará para permutar sua entrada.
O corpo principal do script começa usando dc para converter a entrada de hexadecimal em binário. Os bits zero principais são preservados prefixando a entrada com F e descartando os quatro bits. O resultado é alimentado para awk , que imprime um comando que informa dc para converter de binário para hexadecimal, depois a saída permutada e, em seguida, um comando que diz dc para imprimir e sair. Isto é claro alimentado em dc . Finalmente, sed é usado novamente para garantir zeros à esquerda, se apropriado.
A entrada vem em stdin , saída em stdout , assim:
#!/bin/sh
# file: swap-bits
target_order='D5679123C4EF80AB'
indices() {
printf '%s\n' "$1" \
| sed 's/./$ echo B455 | ./swap-bits
CB15
1+p\n/g' \
| sed '1s/^/10o16i/' \
| dc \
| sed 's/^/substr( $0, /' \
| sed 's/$/, 1 )/' \
| tr '\n' ' '
echo
}
sed 's/^/2o16iF/' \
| sed 's/$/p/' \
| dc \
| sed 's/....//' \
| awk "{ print \"16o2i\" $(indices ${target_order}) \"pq\" }" \
| dc \
| sed 's/^/0000/' \
| sed 's/.*\(....\)$//'