12

I wanted to output a string of all the ascii characters with the following command

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

The output of the above command is:

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

It's the first (from the left) digit of each number.

Looking through this site I came across the answer to my problem How to print all printable ASCII chars in CLI?, however I still don't understand why my original snippet does not output the ascii characters as intended.

  • 1
    POSIX dictates this, here's a comp.unix.shell thread on why it's the right thing ;) – sr_ Aug 4 '12 at 11:36
  • @sr_ Thanks for pointing out the thread. It had the explanation I was looking for. – Ifthikhan Aug 4 '12 at 18:06
11

You can't directly print the ascii codes by using the printf "%c" $i like in C.

You have to first convert the decimal value of i into its octal value and then you have to print it using using printf and putting \ in front of their respective octal values.

To print A, you have to convert the decimal 65 into octal, i.e. 101, and then you have to print that octal value as:

printf "\101\n"

This will print A.

So you have to modify it to :

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

But by using awk you can directly print like in C language

awk 'BEGIN{for(i=32;i<=127;i++)printf "%c",i}';echo
  • 7
    In bash and zsh this can be done without the loop and without the external command: printf $(printf '\%o' {32..127}). – manatwork Aug 4 '12 at 12:02
  • @manatwork: ya exactly..thanks a lot for pointing it out.. – pradeepchhetri Aug 4 '12 at 12:08
  • 1
    @pradeepchhetri : Thank you for the detailed response and it seemed to cover most of the required details (hence I choose your answer). However I guess it missed out an important piece of information which can be found in the following message at unix.derkeiler.com/Newsgroups/comp.unix.shell/2007-07/…. It states that "The argument operands shall be treated as strings if the corresponding conversion specifier is b, c, or s..." – Ifthikhan Aug 4 '12 at 18:11
  • Isn't (char)(127) backspace or something like that. Whatever it is, it appears as one of the hex-boxes or whatever they are called. If you want only the "printable" (i.e. readable), just go to 126. Also, nice thought with the octal. That's clever; I was thinking in terms of hexadecimal (like printf '\x%x; {32..126} ... or 127, I guess, since all of you did it, too), but it doesn't work. Octal saves the day! :) Finally, @Ifthikhan, I'm not sure what you mean. awk often uses C-style commands and nowhere else is %c used. Using octal numbers is different than using one-byte characters. – Dylan Nov 20 '14 at 14:31
3

%c Interprets the associated argument as char: only the first character of a given argument is printed

You seem to already have a way to print them, but here is one variant.

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

You need printf, but only once; you can replace one use of printf by the simpler and more efficient echo plus Bash escape sequences:

With hexagesimals:

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

With octals:

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.