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.

50
demandé sur Steven Penny 2009-10-22 06:52:50

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'
54
répondu bdonlan 2009-10-22 02:55:27

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.

71
répondu josch 2011-10-06 23:00:37

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"
12
répondu Fa11enAngel 2012-10-31 15:03:46

Bash one-liner

echo -n "5a" | while read -N2 code; do printf "\x$code"; done
9
répondu user3132194 2014-09-30 04:23:54

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
3
répondu ghostdog74 2009-10-22 03:31:47

dc peut convertir entre les bases numériques:

$ echo 5a | (echo 16i; tr 'a-z' 'A-Z'; echo P) | dc
Z$
2
répondu Roger Willcocks 2014-12-30 20:07:28

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
2
répondu Jack O'Connor 2015-10-14 15:15:24
echo 5a | python -c "import sys; print chr(int(sys.stdin.read(),base=16))"
1
répondu unutbu 2009-10-22 03:04:45

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.

1
répondu Vouze 2014-09-08 12:54:25

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=
0
répondu Steven Penny 2014-12-16 09:16:02

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
0
répondu tehmoon 2017-11-12 21:56:46

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
0
répondu kenorb 2018-07-12 21:46:46