web-dev-qa-db-fra.com

Convertir une chaîne en hexadécimal en ligne de commande

J'essaie de convertir "Hello" en 48 65 6c 6c 6f en hexadécimal aussi efficacement que possible en utilisant la ligne de commande.

J'ai essayé de regarder printf et Google, mais je ne peux aller nulle part.

Toute aide grandement appréciée.

Merci d'avance,

20
Eamorr
echo -n "Hello" | od -A n -t x1

Explication:

  • Le programme echo fournira la chaîne à la commande suivante.
  • Le drapeau -n indique à echo de ne pas générer de nouvelle ligne à la fin du "Bonjour".
  • Le programme od est le programme "octal dump". (Nous fournirons un drapeau pour lui dire de le vider en hexadécimal au lieu d'octal.)
  • L'indicateur -A n est l'abréviation de --address-radix=n, n étant l'abréviation de "aucun". Sans cette partie, la commande afficherait un préfixe d'adresse numérique laid sur le côté gauche. Ceci est utile pour les vidages volumineux, mais pour une chaîne courte, il est inutile.
  • L'indicateur -t x1 est l'abréviation de --format=x1, x étant l'abréviation de "hexidecimal" et le 1 signifiant 1 octet.
42
TMS

Evidemment, @TMS ne peut pas RTFM. (voir ses commentaires à sa réponse précédente)

Si vous voulez faire cela et supprimer les espaces dont vous avez besoin:

echo -n "Hello" | od -A n -t x1 | sed 's/ *//g'

Les deux premières commandes du pipeline sont bien expliquées par @TMS dans sa réponse, telle que modifiée par @James. La dernière commande diffère du commentaire @TMS en ce qu’elle est correcte et a été testée. L'explication est la suivante:

  • sed est un s tream ed itor.
  • s est la commande s ubstitute.
  • / ouvre une expression régulière - n'importe quel caractère peut être utilisé. / est conventionnel, mais peu pratique pour le traitement, disons XML ou les noms de chemins.
  • / ou le caractère alternatif que vous avez choisi, ferme l'expression régulière et ouvre la chaîne de substitution.
  • Dans / */, le * correspond à n'importe quelle séquence du caractère précédent (dans ce cas , Un espace).
  • / ou le caractère alternatif que vous avez choisi ferme la chaîne de substitution. Dans ce cas, la chaîne de substitution // est vide, c'est-à-dire que la correspondance est supprimée .
  • g est l’option de faire cette substitution g lobally sur chaque ligne au lieu de d’une seule fois pour chaque ligne.
  • Les guillemets empêchent l’analyseur de commandes de s’embrouiller - l’ensemble de la séquence Est passé à sed comme première option, à savoir un script sed.

@TMS brain child (sed 's/^ *//') supprime uniquement les espaces au début de chaque ligne (^ correspond au début de la ligne - 'espace de mappage' dans sed- speak).

Si vous souhaitez également supprimer les nouvelles lignes, le moyen le plus simple consiste à ajouter

| tr -d '\n'

aux tuyaux de commande. Il fonctionne comme suit:

  • | alimente le flux précédemment traité vers l'entrée standard de cette commande.
  • tr est la commande tr anslate.
  • -d spécifie la suppression des caractères de correspondance.
  • Les citations répertorient les caractères de votre correspondance - dans ce cas, juste une nouvelle ligne (\n). Traduire ne fait correspondre que des caractères simples, pas des séquences.

sed est particulièrement retardé lorsqu'il s'agit de nouvelles lignes. En effet, sed est l’une des commandes unix les plus anciennes. Elle a été créée avant que les utilisateurs ne sachent vraiment ce qu’ils faisaient. Les logiciels hérités omniprésents l'empêchent d'être corrigés. Je le sais parce que je suis né avant la naissance de unix.

L'origine historique du problème était l'idée selon laquelle une nouvelle ligne était un séparateur de ligne et non une partie de la ligne. Il a donc été supprimé par les utilitaires de traitement de ligne et réinséré par les utilitaires de sortie. Le problème est que cela suppose des hypothèses sur la structure des données utilisateur et impose des restrictions non naturelles dans de nombreux paramètres. L’incapacité de sed à supprimer facilement les nouvelles lignes est l’un des exemples les plus courants de cette idéologie malformée qui cause du chagrin.

Il est possible de supprimer les nouvelles lignes avec sed - c’est simplement que toutes les solutions que je connais font que sed traite le fichier entier en même temps, ce qui étouffe les très gros fichiers, annulant ainsi l’utilité d’un éditeur de flux. Toute solution qui conserve le traitement de ligne, si possible, constituerait un nid illisible de plusieurs canaux.

Si vous insistez pour utiliser sed, essayez:

sed -z 's/\n//g'

-z indique à sed d'utiliser nulls comme séparateurs de ligne.

En interne, une chaîne dans C se termine par un null. L'option -z est également une conséquence de Legacy, fournie pour aider les programmeurs C à utiliser un fichier temporaire rempli de chaînes C- et non encombré par des nouvelles lignes. Ils peuvent alors facilement lire et traiter une chaîne à la fois. Là encore, les premières hypothèses sur les cas d'utilisation imposent des restrictions artificielles aux données des utilisateurs.

Si vous omettez l'option g, cette commande supprime uniquement la première nouvelle ligne. Avec l'option -z, l'option sed interprète l'intégralité du fichier comme une seule ligne (à moins que des valeurs nulles imbriquées ne soient incorporées dans le fichier), se terminant par un null, ce qui étouffe également les gros fichiers.

Tu pourrais penser

sed 's/^/\x00/' | sed -z 's/\n//' | sed 's/\x00//'

pourrait fonctionner. La première commande met un zéro à l'avant de chaque ligne ligne par ligne, ce qui entraîne \n\x00 à terminer chaque ligne. La deuxième commande supprime une nouvelle ligne de chaque ligne, maintenant délimitée par des valeurs NULL. Il n'y aura qu'une nouvelle ligne en vertu de la première commande. Il ne reste que les faux nuls. Jusqu'ici tout va bien. L'idée cassée ici est que le canal va alimenter la dernière commande ligne par ligne, puisque c'est ainsi que le flux a été construit. En fait, la dernière commande, telle qu’elle est écrite, ne supprimera qu’une valeur null, car l’ensemble du fichier n’a pas de nouvelle ligne et n’est donc qu’une ligne.

L'implémentation simple de canal utilise un fichier temporaire intermédiaire et toutes les entrées sont traitées et introduites dans le fichier. La commande suivante peut être en cours d'exécution dans un autre thread, lisant simultanément ce fichier, mais elle ne voit que le flux dans son ensemble (même si elle est incomplète) et n'a aucune conscience des limites du bloc alimentant le fichier. Même si le canal est un tampon de mémoire, la commande suivante voit le flux dans son ensemble. Le défaut est inextricablement cuit en sed.

Pour que cette approche fonctionne, vous avez besoin d'une option g sur la dernière commande. Encore une fois, elle étouffe les fichiers volumineux.

La ligne de fond est la suivante: n'utilisez pas sed pour traiter les nouvelles lignes.

3

Une solution efficace consiste à supprimer le "*". Il n’est pas nécessaire que l’obligation initiale supprime simplement les espaces si vous souhaitez remplacer un caractère réel, comme suit.

echo -n "Hello" | od -A n -t x1 | sed 's/ /%/g'

%48%65%6c%6c%6f

Donc, je considère cela comme une amélioration répondant au Q original puisque la déclaration fait maintenant exactement ce qui est requis, pas seulement apparemment.

1
Tony Su