• [^] # Re: xxd

    Posté par (site web personnel) . En réponse à la dépêche get-tracks.sh : extraire des pistes d'un fichier audio. Évalué à 6. Dernière modification le 25 janvier 2022 à 19:03.

    Très bien, affûtons notre unix-fu.

    Traduction de xxd -p -c 1

    En premier, il nous faut une traduction d'une entrée quelconque en une colonne hexa. Tu l'as pratiquement donnée avec od, mais il manque de mettre les valeurs en colonne.

    # Convert input into hexadecimal and a single byte per line.
    to_hex_one_column() {
     od -An -tx1 | awk '{for(i=1;i<=NF;i++){ print $i }}'
    }

    Traduction de xxd -p -r

    Maintenant, (presque) l'inverse avec tr, bc (et dc), od et awk. « Presque » car l'entrée n'est pas sur une seule colonne, puisque je regroupe des caractères pour traiter l'UTF-8. Je mets tous les caractères d'une ligne sur une seule ligne. L'entrée peut ressembler à ceci :

    61 62 0a
    63 64 0a
    

    Et là, on aimerait bien passer tout ça à awk pour qu'il traduise ça en caractères affichables via sa fonction printf. Mais il lui faut un nombre en base 10 et je sais pas traduire l'hexa facilement avec awk (hors version GNU), donc on va passer par quelques étapes supplémentaires.

    Première chose à faire, remettre tout ça en une seule colonne : tr " " "\n".

    Ensuite, on veut passer l'entrée à bc (et par conséquent à dc) pour qu'il convertisse l'hexadécimal en décimal. Attention, bc est sensible à la casse, donc il faut mettre l'hexadécimal en majuscules :

    uppercase() tr "[a-z]" "[A-Z]"

    Maintenant la conversion avec bc :

    # One col hexa to one col decimal.
    from_hex_to_decimal() {
     { echo "obase=10;ibase=16;" ; cat ; } | bc
    }

    Et enfin, on fait la traduction décimal -> caractères UTF-8 avec awk et sa fonction printf.

    # One col decimal to plain text.
    from_dec() awk '{ printf ("%c", 1ドル + 0) }'

    Et donc la fonction complète qui passe de l'hexadécimal à la sortie finale :

    # Reverse hexadecimal (with space separators) to original value.
    from_hex() {
     tr " " "\n" | uppercase | from_hex_to_decimal | from_dec
    }

    Je ne sais pas trop quoi penser du résultat. Je l'ai testé et ça semble fonctionner, mais est-ce suffisamment « simple » ? Est-ce qu'on aurait pas plus simple encore ?