Binaire à hexadécimal et décimal dans un script shell

20

J'ai un contexte où j'ai besoin de convertir le binaire en hexadécimal et décimal et vice-versa dans un script shell. Quelqu'un peut-il me suggérer un outil pour cela?

Bangi
la source
7
En voyant les réponses récentes, vous devriez peut-être spécifier si «binaire» signifie un nombre binaire ou un fichier binaire .
manatwork
1
doublon
intersite

Réponses:

38

Il est assez simple de faire la conversion à partir de binaire en bash pur ( echoet printfsont intégrés):

Binaire à décimal

$ echo "$((2#101010101))"
341

Binaire à hexadécimal

$ printf '%x\n' "$((2#101010101))"
155

Revenir au binaire en utilisant bash seul est un peu plus complexe, donc je vous suggère de voir les autres réponses pour trouver des solutions à cela.

Chris Down
la source
que diriez-vous de décimal en hexadécimal.
Bangi
2
@Bangi Il suffit de faire printf '%x\n' 10, par exemple.
Chris Down le
1
Quel est l'intérêt d'utiliser printf %dbin2dec? $(( ... ))donne déjà un résultat décimal, echosuffit.
Andrea Corbellini
@AndreaCorbellini - Préférence personnelle. En général, j'utilise printf '%s\n' fooau lieu de echopour diverses raisons (principalement la portabilité), pour la même raison, je ne l'utilise pas ici.
Chris Down
@ChrisDown: Je pensais que cette question concernait explicitement Bash (qui a une fonction echointégrée bien implémentée ). Ma faute!
Andrea Corbellini
16

En supposant que par binaire, vous voulez dire des données binaires comme dans des données avec toute valeur d'octet possible, y compris 0, et non des nombres en base 2:

Pour convertir de binaire, od(standard), xxd(livré avec vim) ou perll » unpackviennent à l' esprit.

od -An -vtu1 # for decimal
od -An -vtx1 # for hexadecimal

xxd -p # for hexa

perl -pe 'BEGIN{$\="\n";$/=\30};$_=unpack("H*",$_)' # like xxd -p

# for decimal:
perl -ne 'BEGIN{$\="\n";$/=\30;$,=" "}; print unpack("C*",$_)'

Maintenant, pour se reconvertir à binaire, awk(standard), xxd -rou perlde pack:

De la sortie décimale de od -tu1ou perlau - dessus:

LC_ALL=C awk '{for (i = 1; i <= NF; i++) printf "%c", $i}'
perl -ape '$_=pack("C*",@F)'

Depuis l'hexa perlou xxd -pau - dessus:

xxd -r -p
perl -pe 'chomp;$_=pack("H*",$_)'
Stéphane Chazelas
la source
13

Vous pouvez utiliser bc pour cela en manipulant les paramètres ibaseet obase:

L'astuce est que vous devez être explicite sur les bases. Donc, si votre ibase est 2, alors si vous définissez votre obase sur 10, il ne fera rien, car 10 en binaire est 2. Par conséquent, vous devez utiliser la notation hexadécimale.

Donc binaire à décimal serait (attention à ce que obase soit A)

Binaire à décimal:

$> echo 'ibase=2;obase=A;11110001011010'|bc
15450

Binaire à hex:

$> echo 'ibase=2;obase=10000;11110001011010'|bc
3C5A

Si la «base de sortie» obaseest modifiée en premier, cela devrait être plus facile:

$> echo 'obase=10;ibase=2;11110001011010'|bc
15450
$> echo 'obase=16;ibase=2;11110001011010'|bc
3C5A
psarossy
la source
6
Ce deuxième exemple est faux - «F» serait la base 15, pas 16 (la décimale 16 dans l'hex est 10, pas F). Essayez echo 'ibase=2;obase=F;1111qui doit être égal à 15 décimal, c.-à-d. F en hex. Il apparaît comme 10, qu'il est en base 15 (chiffres 0-E). Il est également plus facile si vous déclarez la obase première , par exemple: echo 'obase=16;ibase=2;1111'|bc. Pas de confusion.
goldilocks
2
Maintenant c'est pire. Une fois que vous avez défini ibase, vous devez fournir une entrée dans cette base, même pour obase. Donc, dans votre exemple, ce serait echo 'ibase=2;obase=10000;11110001011010'|bc. Mieux vaut écouter les conseils de goldilocks et inverser l'ordre - premier set obase, puis ibase.
manatwork
3

Si vous entendez convertir des nombres de base 2 en 10 ou 16 et inversement , bcest l'outil standard pour le faire, comme déjà mentionné par psarossy .

decimal=123
binary=$(echo "obase=2;$decimal" | bc)
hex=$(echo "obase=16;ibase=2;$binary" | bc)

Certains shells comme zshont un support intégré pour la conversion de base dans le cadre de leurs opérateurs d'expansion arithmétique:

decimal=123
binary=$(([##2]decimal))
hex=$(([##16]decimal))
hex=$(([##16]2#$binary))
decimal=$((2#$binary))

etc.

Les deux ksh93et zshprennent également en charge:

typeset -i2 binary=123
typeset -i16 dec2hex=123 bin2hex='2#1111'

Mais notez que, une fois développé, $binaryil aura un préfixe 2#ou 16#(avec lequel vous pouvez supprimer ${binary#*#}.

ksh93 prend également en charge:

printf "%..2d\n" 123

pour convertir en binaire.

Stéphane Chazelas
la source
1

Pour une utilisation binaire en hexadécimal: outil xxd sous linux et pour binaire en décimal, vous pouvez utiliser l'outil qalculate.

Pour obtenir de l'aide concernant le type xxd xxd --helpou man xxdsous Linux.

P4cK3tHuNt3R
la source
1

Vous pouvez utiliser PHP:

$ php -r 'printf("%b", 11);'
1011

Ou Perl:

$ perl -e 'print unpack("B*", pack("c", 11))'
00001011

$ perl -e 'print unpack("B*", pack("C", 11))'
00001011

$ perl -e 'print unpack("B*", pack("W", 11))'
00001011

$ perl -e 'print unpack("B*", pack("n", 11))'
0000000000001011

$ perl -e 'print unpack("B*", pack("N", 11))'
00000000000000000000000000001011

Ou POSIX Awk svnpenn / stdlib :

$ awklib 'BEGIN {print mt_basecon(1011, 2, 16)}'
B

$ awklib 'BEGIN {print mt_basecon(1011, 2, 10)}'
11

$ awklib 'BEGIN {print mt_basecon("B", 16, 2)}'
1011

$ awklib 'BEGIN {print mt_basecon(11, 10, 2)}'
1011
Steven Penny
la source
0

Comme mentionné dans la réponse précédente, vous pouvez faire du binaire en décimal et hexa décimal comme suit dans Bash en utilisant echo et printf. J'ajoute juste ici comment convertir de Decimal et Hex en binaire en utilisant du Bash pur.

Binaire à décimal en utilisant l'écho

echo "$((2#101010101))"
341

Binaire en hexa-décimal en utilisant printf

printf '%x\n' "$((2#101010101))"
155

Conversion décimale en binaire en utilisant uniquement Bash

En utilisant uniquement Bash, si vous souhaitez convertir des décimales en binaires, vous pouvez le faire comme suit:

touch dec2bin && chmod +x "$_" && vim "$_"

Et puis copiez et collez les éléments suivants:

#!/bin/bash
## converting decimal integer to binary, pass int as a parameter
num=$1;
dec2bin()
{   [ "$num" == "" ] && { printf "Error: Pass an integer\n"; exit 1; };
    op=2; ## Since we're converting to binary
    quo=$(( $num / $op)); rem=$(( $num % $op)); ## quotient and remainder
    remarray=(); ## array for putting remainder inside array
    remarray+=("$rem"); ## array expansion
        until [[ $quo -eq 0 ]]; do
            num=$quo; quo=$(( $num / $op)); ## looping to get all remainder untill 0
            rem=$(( $num % $op)); remarray+="$rem"; ## array expansion
        done
    binary=$(echo "${remarray[@]}" | rev); ## reversing array
    printf "$binary\n"; ## printing reversed array
}
main()
{   [[ -n ${num//[0-9]/} ]] &&
        { printf "Error: $num is not an integer bruv!\n"; return 1;
        } || { dec2bin $num; }
}
main;

Et puis essayez-le d'où vous avez enregistré:

./dec2bin 420
110100100

Un entier doit être ajouté !!

./dec2bin 420.py
420.py is not an integer bruv!

Conversion hexadécimale en binaire en utilisant uniquement Bash

De même, hexadécimal à binaire, comme suit en utilisant uniquement bash:

#!/usr/local/bin/bash
## converting hexadecimal to binary, pass hex as a parameter
hex=$1;
hex2bin()
{   [ "$hex" == "" ] && { printf "Error: Pass a hex\n"; exit 1; };
    op=2; num=$((16#$hex)); ## converting hex to integer
    quo=$(( $num/ $op)); rem=$(( $num% $op)); ## quotient and remainder
    remarray=(); remarray+=("$rem"); ## array expansion
        until [[ $quo -eq 0 ]]; do
            num=$quo; quo=$(( $num / $op)); ## looping to get all remainder untill 0
            rem=$(( $num % $op)); remarray+="$rem"; ## array expansion
        done
    binary=$(echo "${remarray[@]}" | rev); ## reversing array
    printf "$binary\n"; ## printing reversed array
}
main()
{
[[ -n ${hex//[0-9,A-F,a-f]/} ]] &&
    { printf "Error: $hex is not a hex bruv!\n"; return 1;
    } || { hex2bin $hex; }
}
main;

Par exemple:

./hex2bin 1aF
110101111

L'hex doit être passé:

./hex2bin.bash XyZ
XyZ is not a hexa decimal number bruv!
Rakib Fiha
la source