Al imprimir caracteres decimales a ascii, mi comando no sale como se esperaba

14

Quería generar una cadena de todos los caracteres ascii con el siguiente comando

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

La salida del comando anterior es:

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

Es el primer dígito (desde la izquierda) de cada número.

Al examinar este sitio, encontré la respuesta a mi problema. ¿Cómo imprimir todos los caracteres ASCII imprimibles en la CLI? , sin embargo, todavía no entiendo por qué mi fragmento original no muestra los caracteres ascii como se esperaba.

Ifthikhan
fuente
1
POSIX dicta esto, aquí hay un comp.unix.shellhilo sobre por qué es lo correcto;)
sr_
@sr_ Gracias por señalar el hilo. Tenía la explicación que estaba buscando.
Ifthikhan

Respuestas:

13

No puede imprimir directamente los códigos ASCII utilizando los printf "%c" $isimilares en C.

Primero debe convertir el valor decimal de i en su valor octal y luego debe imprimirlo usando printfy poniendo \delante de sus respectivos valores octales.

Para imprimir A, debe convertir el decimal 65 en octal, es decir, 101, y luego debe imprimir ese valor octal como:

printf "\101\n"

Esto se imprimirá A.

Entonces tienes que modificarlo para:

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

Pero al usarlo awkpuedes imprimir directamente como en lenguaje C

awk 'BEGIN{for(i=32;i<=127;i++)printf "%c",i}';echo
Pradeepchhetri
fuente
77
En bashy zshesto se puede hacer sin el bucle y sin el comando externo: printf $(printf '\%o' {32..127}).
manatwork
@manatwork: sí, exactamente ... muchas gracias por señalarlo ...
#
1
@pradeepchhetri: Gracias por la respuesta detallada y parecía cubrir la mayoría de los detalles requeridos (por lo tanto, elijo su respuesta). Sin embargo, supongo que se perdió una información importante que se puede encontrar en el siguiente mensaje en unix.derkeiler.com/Newsgroups/comp.unix.shell/2007-07/… . Establece que "Los operandos del argumento se tratarán como cadenas si el especificador de conversión correspondiente es b, c o s ..."
Ifthikhan
No es (char)(127)retroceso o algo así. Sea lo que sea, aparece como una de las cajas hexadecimales o como se llamen. Si solo desea lo "imprimible" (es decir, legible), simplemente vaya a 126. Además, un buen pensamiento con el octal. Eso es inteligente; Estaba pensando en términos de hexadecimal (como printf '\x%x; {32..126}... o 127, supongo, ya que todos ustedes también lo hicieron), pero no funciona. ¡Octal salva el día! :) Finalmente, @ Ifthikhan, no estoy seguro de lo que quieres decir. awka menudo usa comandos de estilo C y no se %cusa ningún otro lugar . Usar números octales es diferente a usar caracteres de un byte.
Dylan
3

%c Interpreta el argumento asociado como char: solo se imprime el primer carácter de un argumento dado

Parece que ya tiene una forma de imprimirlos, pero aquí hay una variante.

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

Necesitas printf, pero solo una vez; puede reemplazar un uso de printfpor las echosecuencias de escape Bash más simples y más eficientes :

Con hexagesimales:

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

Con los octales:

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