web-dev-qa-db-fra.com

linux shell scripting: chaîne hexadécimale en octets

Disons que j'ai une chaîne 5a. Il s'agit de la représentation hexadécimale de la lettre Z ASCII J'ai besoin de connaître une commande Linux Shell qui prend une chaîne hexagonale .__ et génère les octets binaires qu'elle 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.

54
Krystian Cybulski
echo -n 5a | Perl -pe 's/([0-9a-f]{2})/chr hex $1/gie'

Notez que cela ne sautera pas les caractères non hexadécimaux. Si vous voulez seulement l'hex (pas de blanc de la chaîne d'origine, etc.):

echo 5a | Perl -ne 's/([0-9a-f]{2})/print chr hex $1/gie'

De plus, zsh et bash prennent cela en charge de manière native dans echo:

echo -e '\x5a'
57
bdonlan

J'avais l'habitude de faire cela 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 également Perl (à mon avis, cela ne fait pas partie d'un système minimal), j'ai finalement utilisé sed, xargs et printf comme ceci:

echo -n 5a | sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI' | xargs printf

La plupart du temps, je ne souhaite convertir que quelques octets et c'est correct pour de telles tâches. L'avantage de cette solution par rapport à celle de ghostdog74 est qu'elle permet de convertir automatiquement les chaînes hexadécimales de longueurs arbitraires. xargs est utilisé car printf ne lit pas l’entrée standard.

79
josch

Vous pouvez le faire en écho seulement et sans les autres trucs. N'oubliez pas d'ajouter "-n" ou vous obtiendrez un saut de ligne automatiquement:

echo -n -e "\x5a"
13
Fa11enAngel

Bash one-liner

echo -n "5a" | while read -N2 code; do printf "\x$code"; done
9
user3132194

selon l'endroit où vous avez "5a", vous pouvez simplement y ajouter\x et passer à printf 

$ a=5a
$ a="\x${a}"
$ printf "$a"
Z
3
ghostdog74

dc peut convertir entre des bases numériques:

$ echo 5a | (echo 16i; tr 'a-z' 'A-Z'; echo P) | dc
Z$
2
Roger Willcocks

Certains one-liners python3 qui fonctionnent avec un nombre quelconque d’octets.

Décodage d'hex (avec strip, de sorte 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

Hexagone de codage:

$ echo foo | python3 -c "import sys, binascii; print(binascii.hexlify(sys.stdin.buffer.read()).decode())"
666f6f0a
2
Jack O'Connor

Voici un script pur bash (comme printf est une commande intégrée à 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
Vouze
echo 5a | python -c "import sys; print chr(int(sys.stdin.read(),base=16))"
1
unutbu

GNU awk 4.1

awk -niord '$0=chr("0x"RT)' RS=.. ORS=

Notez que si vous répondez à cela, un octet nul supplémentaire sera généré.

$ echo 595a | awk -niord '$0=chr("0x"RT)' RS=.. ORS= | od -tx1c
0000000  59  5a  00
          Y   Z  \0

Utilisez plutôt printf

$ printf 595a | awk -niord '$0=chr("0x"RT)' RS=.. ORS= | od -tx1c
0000000  59  5a
          Y   Z

Notez également que GNU awk produit UTF-8 par défaut

$ printf a1 | awk -niord '$0=chr("0x"RT)' RS=.. ORS= | od -tx1
0000000 c2 a1

Si vous traitez avec des caractères extérieurs à ASCII et que vous allez coder Base64, vous pouvez désactiver UTF-8 avec -b

echo 5a | sha256sum | awk -bniord 'RT~/\w/,$0=chr("0x"RT)' RS=.. ORS=
0
Steven Penny

Selon @Randal comment , vous pouvez utiliser Perl, par exemple.

$ printf 5a5a5a5a | Perl -lne 'print pack "H*", $_'
ZZZZ

et inversement:

$ printf ZZZZ | Perl -lne 'print unpack "H*", $_'
5a5a5a5a

Un autre exemple avec le fichier:

$ printf 5a5a5a5a | Perl -lne 'print pack "H*", $_' > file.bin
$ Perl -lne 'print unpack "H*", $_' < file.bin
5a5a5a5a
0
kenorb

Semblable à ma réponse ici: Script Linux Linux: nombre hexadécimal en chaîne binaire

Vous pouvez le faire avec le même outil comme ceci (en utilisant un caractère imprimable ascii au lieu de 5a):

echo -n 616263 | cryptocli dd -decoders hex

Produira le résultat suivant:

abcd
0
tehmoon