Linux shell scripting: chaîne hex aux octets
disons que j'ai une chaîne de caractères 5a
. C'est la représentation hexagonale des ASCII
lettre Z. j'ai besoin de savoir une commande de shell Linux qui prendra une chaîne hexadécimale
et sortie des octets binaires que la chaîne représente.
donc si je le fais
echo 5a | command_im_looking_for > temp.txt
et j'ouvre temp.txt
, je verrai une lettre Solitaire Z.
12 réponses
echo -n 5a | perl -pe 's/([0-9a-f]{2})/chr hex /gie'
notez que cela ne sautera pas les caractères non-hexadécimaux. Si vous voulez juste l'hexagone (pas d'espace de la chaîne d'origine...):
echo 5a | perl -ne 's/([0-9a-f]{2})/print chr hex /gie'
aussi, zsh
et bash
soutiennent cela nativement dans echo
:
echo -e '\x5a'
j'avais l'habitude de le faire en utilisant xxd
echo -n 5a | xxd -r -p
mais ensuite j'ai réalisé que dans Debian/Ubuntu, xxd fait partie de vim-common et pourrait donc ne pas être présent dans un système minimal. Pour éviter perl (imho également ne faisant pas partie d'un système minimal) j'ai fini par utiliser sed, xargs et printf comme ceci:
echo -n 5a | sed 's/\([0-9A-F]\{2\}\)/\\\x/gI' | xargs printf
la plupart du temps Je ne veux convertir que quelques octets et c'est OK pour de telles tâches. L'avantage de cette solution sur celle de ghostdog74 est que cela permet de convertir automatiquement des chaînes de hexagones de longueurs arbitraires. xargs est utilisé parce que printf ne lit pas à partir de l'entrée standard.
Vous pouvez le faire par le biais d'echo et sans les autres trucs. N'oubliez pas d'ajouter "-n" ou vous obtiendrez un linebreak automatiquement:
echo -n -e "\x5a"
Bash one-liner
echo -n "5a" | while read -N2 code; do printf "\x$code"; done
selon l'endroit où vous avez eu ce "5a', vous pouvez juste y ajouter \x et passer à printf
$ a=5a
$ a="\x${a}"
$ printf "$a"
Z
dc peut convertir entre les bases numériques:
$ echo 5a | (echo 16i; tr 'a-z' 'A-Z'; echo P) | dc
Z$
certains monolithes python3 qui fonctionnent avec n'importe quel nombre d'octets.
décodant hex ( avec strip
, pour qu'il soit correct d'avoir une nouvelle ligne sur stdin):
$ echo 666f6f0a | python3 -c "import sys, binascii; sys.stdout.buffer.write(binascii.unhexlify(input().strip()))"
foo
Codage hexadécimal:
$ echo foo | python3 -c "import sys, binascii; print(binascii.hexlify(sys.stdin.buffer.read()).decode())"
666f6f0a
echo 5a | python -c "import sys; print chr(int(sys.stdin.read(),base=16))"
voici un script bash pur (comme printf est un builtin bash):
#warning : spaces do matter
die(){ echo "$@" >&2;exit 1;}
p=48656c6c6f0a
test $((${#p} & 1)) == 0 || die "length is odd"
p2=''; for ((i=0; i<${#p}; i+=2));do p2=$p2\x${p:$i:2};done
printf "$p2"
si bash est déjà en cours d'exécution, cela devrait être plus rapide que toute autre solution qui lance un nouveau processus.
GNU awk 4.1
awk -niord '"151900920"=chr("0x"RT)' RS=.. ORS=
notez que si vous faites écho à ceci il produira un octet nul supplémentaire
$ echo 595a | awk -niord '"151910920"=chr("0x"RT)' RS=.. ORS= | od -tx1c
0000000 59 5a 00
Y Z "151910920"
au lieu d'utiliser printf
$ printf 595a | awk -niord '"151920920"=chr("0x"RT)' RS=.. ORS= | od -tx1c
0000000 59 5a
Y Z
notez aussi que GNU awk produit UTF-8 par défaut
$ printf a1 | awk -niord '"151930920"=chr("0x"RT)' RS=.. ORS= | od -tx1
0000000 c2 a1
si vous avez affaire à des personnages en dehors D'ASCII, et vous allez être
Base64 encodant la chaîne résultante, vous pouvez désactiver UTF-8 avec -b
echo 5a | sha256sum | awk -bniord 'RT~/\w/,"151940920"=chr("0x"RT)' RS=.. ORS=
similaire à ma réponse ici: Linux shell scripting: nombre hex à chaîne binaire
vous pouvez le faire avec le même outil comme ceci (en utilisant le caractère imprimable ascii au lieu de 5a
):
echo -n 616263 | cryptocli dd -decoders hex
produira le résultat suivant:
abcd
comme dans @Randal comment , vous pouvez utiliser perl
, par exemple
$ printf 5a5a5a5a | perl -lne 'print pack "H*", $_'
ZZZZ
et d'autres:
$ printf ZZZZ | perl -lne 'print unpack "H*", $_'
5a5a5a5a
un autre exemple avec fichier:
$ printf 5a5a5a5a | perl -lne 'print pack "H*", $_' > file.bin
$ perl -lne 'print unpack "H*", $_' < file.bin
5a5a5a5a