Imprimindo um caractere decimal para ascii, meu comando não sai como pretendido

14

Eu queria gerar uma sequência de todos os caracteres ascii com o seguinte comando

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

A saída do comando acima é:

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

É o primeiro dígito (da esquerda) de cada número.

Procurando neste site, me deparei com a resposta para o meu problema Como imprimir todos os caracteres ASCII imprimíveis na CLI? , no entanto, ainda não entendo por que meu snippet original não gera os caracteres ascii como pretendido.

Ifthikhan
fonte
1
POSIX dita isso, aqui está uma comp.unix.shelllista de discussão sobre por que isso é a coisa certa;)
sr_
@sr_ Obrigado por apontar o tópico. Tinha a explicação que eu estava procurando.
Ifthikhan

Respostas:

13

Você não pode imprimir diretamente os códigos ascii usando o printf "%c" $itipo em C.

Você deve primeiro converter o valor decimal de i em seu valor octal e depois imprimi-lo usando oprintf e colocando \na frente dos respectivos valores octais.

Para imprimir A, você precisa converter o decimal 65 em octal, ou seja, 101 e, em seguida, imprimir esse valor octal como:

printf "\101\n"

Isso imprimirá A .

Então você precisa modificá-lo para:

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

Mas usando awkvocê pode imprimir diretamente como na linguagem C

awk 'BEGIN{for(i=32;i<=127;i++)printf "%c",i}';echo
pradeepchhetri
fonte
7
Em bashe zshisso pode ser feito sem o loop e sem o comando externo: printf $(printf '\%o' {32..127}).
manatwork
@manatwork: ya exactly..thanks muito para apontar isso ..
pradeepchhetri
1
@pradeepchhetri: Obrigado pela resposta detalhada e parecia cobrir a maioria dos detalhes necessários (por isso, escolhi sua resposta). No entanto, acho que ele perdeu uma informação importante que pode ser encontrada na seguinte mensagem em unix.derkeiler.com/Newsgroups/comp.unix.shell/2007-07/… . Ele afirma que "os operandos do argumento devem ser tratados como cadeias de caracteres se o especificador de conversão correspondente for b, c ou s ..."
Ifthikhan
Não é (char)(127)backspace ou algo assim. Seja o que for, aparece como uma das caixas hexagonais ou como elas são chamadas. Se você quiser apenas o "imprimível" (isto é, legível), vá para 126. Além disso, um bom pensamento com o octal. Isso é inteligente; Eu estava pensando em termos de hexadecimal (como printf '\x%x; {32..126}... ou 127, acho, já que todos vocês fizeram isso também), mas não funciona. Octal salva o dia! :) Finalmente, @Ifthikhan, não sei ao certo o que você quer dizer. awkgeralmente usa comandos no estilo C e em nenhum outro lugar é %cusado. O uso de números octais é diferente do uso de caracteres de um byte.
Dylan
3

%c Interpreta o argumento associado como char: apenas o primeiro caractere de um determinado argumento é impresso

Você parece já ter uma maneira de imprimi-los, mas aqui está uma variante.

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

Você precisa printf, mas apenas uma vez; você pode substituir um uso printfpelas echosequências de escape Bash mais simples e mais eficientes :

Com hexagesimais:

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

Com octais:

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