Impression du caractère décimal en caractère ascii, ma commande ne s'affiche pas comme prévu

14

Je voulais sortir une chaîne de tous les caractères ascii avec la commande suivante

for i in `seq 32 127`; do printf "%c" $i; done

La sortie de la commande ci-dessus est:

33333334444444444555555555566666666667777777777..............

C'est le premier chiffre (à partir de la gauche) de chaque numéro.

En parcourant ce site, je suis tombé sur la réponse à mon problème Comment imprimer tous les caractères ASCII imprimables en CLI? , mais je ne comprends toujours pas pourquoi mon extrait d'origine ne génère pas les caractères ascii comme prévu.

Ifthikhan
la source
1
POSIX le dicte, voici un comp.unix.shellfil sur pourquoi c'est la bonne chose;)
sr_
@sr_ Merci d'avoir signalé le fil. Il y avait l'explication que je cherchais.
Ifthikhan

Réponses:

13

Vous ne pouvez pas imprimer directement les codes ascii en utilisant le printf "%c" $imême en C.

Vous devez d'abord convertir la valeur décimale de i en sa valeur octale , puis l'imprimer en utilisant printfet en plaçant \devant leurs valeurs octales respectives.

Pour imprimer A, vous devez convertir la décimale 65 en octal, c'est-à-dire 101, puis vous devez imprimer cette valeur octale comme:

printf "\101\n"

Cela s'imprimera A.

Vous devez donc le modifier pour:

for i in `seq 32 127`; do printf \\$(printf "%o" $i);done;

Mais en utilisant awkvous pouvez directement imprimer comme en langage C

awk 'BEGIN{for(i=32;i<=127;i++)printf "%c",i}';echo
pradeepchhetri
la source
7
Dans bashet zshcela peut se faire sans la boucle et sans la commande externe: printf $(printf '\%o' {32..127}).
manatwork
@manatwork: ya exactement..merci beaucoup de l'avoir signalé ..
pradeepchhetri
1
@pradeepchhetri: Merci pour la réponse détaillée et elle a semblé couvrir la plupart des détails requis (c'est pourquoi j'ai choisi votre réponse). Cependant, je suppose qu'il a manqué une information importante qui peut être trouvée dans le message suivant sur unix.derkeiler.com/Newsgroups/comp.unix.shell/2007-07/… . Il indique que "Les opérandes d'argument doivent être traités comme des chaînes si le spécificateur de conversion correspondant est b, c ou s ..."
Ifthikhan
Ce n'est pas un (char)(127)retour arrière ou quelque chose comme ça. Quoi qu'il en soit, il apparaît comme l'une des cases hexagonales ou comme on les appelle. Si vous ne voulez que le "imprimable" (c'est-à-dire lisible), allez simplement au 126. Aussi, belle pensée avec l'octal. C'est malin; Je pensais en termes hexadécimaux (comme printf '\x%x; {32..126}... ou 127, je suppose, puisque vous l'avez tous fait aussi), mais cela ne fonctionne pas. Octal sauve la mise! :) Enfin, @Ifthikhan, je ne sais pas ce que vous voulez dire. awkutilise souvent des commandes de style C et nulle part ailleurs n'est %cutilisée. L'utilisation de nombres octaux est différente de l'utilisation de caractères à un octet.
Dylan
3

%c Interprète l'argument associé comme char: seul le premier caractère d'un argument donné est imprimé

Vous semblez déjà avoir un moyen de les imprimer, mais voici une variante.

for i in `seq 32 127`; do printf "\x$(printf "%x" $i) $i"; done
Peter.O
la source
0

Vous en avez besoin printf, mais une seule fois; vous pouvez remplacer une utilisation de printfpar les echoséquences d'échappement plus simples et plus efficaces de Bash:

Avec hexagesimaux:

for i in `seq 32 127`; do
  echo -ne \\x$(printf %02x $i)
done

Avec octales:

for i in `seq 32 127`; do
  echo -ne \\0$(printf %03o $i)
done
Luchostein
la source