helpThe GNU Bourne-Again SHell - Support: sr #102985, Builtin printf: format...


sr #102985: Builtin printf: format "%c" fails

Submitted by:  None
Submitted on:  Thu 08 Apr 2004 11:31:32 AM UTC  
Category:  None Priority:  5 - Normal
Severity:  3 - Normal Status:  Done
Privacy:  Public Assigned to:  None
Originator Email:  -email is unavailable- Open/Closed:  Open
Operating System:  None

Add a New Comment(Rich Markup)

You are not logged in

Please log in, so followups can be emailed to you.


Wed 25 Mar 2015 02:57:02 PM UTC, comment #3:

Not a bug, close.

Eduardo Bustamante <dualbus>
Thu 28 Nov 2013 07:41:20 AM UTC, comment #2:

The POSIX standard says printf %c is supposed to take a string argument, not an integer. The current behaviour is required by POSIX

quoting the standard:
The argument operands shall be treated as strings if the corresponding conversion specifier is b, c, or s ; otherwise, it shall be evaluated as a C constant, as described by the ISO C standard, with the following extensions: ...

printf lets you do the opposite of what the original submitter wanted, get the ASCII (or Unicode!) value of a character as a string of decimal numbers. Use
charvalue=$(printf '%d' "'$char")

You can do the reverse with
charvalue=65 # ascii value of "A"
oct=$(printf '%03o' "$c")
printf '%b\n' "\\$oct"

After searching a bit after typing most of this, I see I wasn't the first person to try this. (and I was using bc to convert decimal to octal for feeding to printf, instead of using another printf with %o.) So anyway, there are shell snippets floating around using that printf trick,

chr() {
printf \\$(printf '%03o' "$1")

ord() {
printf '%d' "'$1"

but see for more complete safer versions. (e.g. setting LC_CTYPE=C)

Those simple versions don't work with wide characters in a UTF-8 environment. The byte sequence representing a Unicode character in UTF-8 isn't always the same as the character's value (codepoint). The only overlap is in the ASCII range.

It looks like the wooledge BashFAQ even has versions of chr and ord that handle UTF8 properly, though, so check that out.

The naive approach breaks as follows:
e.g. Unicode smiley face is codepoint 0x263a
char=$(perl -e 'print chr(0x263a)')
echo "$char" # prints a smiley face (assuming support Unicode etc.)

Now taking the codepoint for that character
printf '%d' "'$char"

This is simply the decimal representation of 0x263A, and converting that to octal with bc will not produce a sequence of bytes that represent that codepoint in UTF-8.

printf "%s" "$char" | hexdump -b

              1. 342 230 272

(also, oddly, printf "%c" "$char" only outputs the first byte of the UTF-8 representation, 0342. I'm using LANG=en_CA.utf8 on Ubuntu GNU/Linux)

printf '\342\230\272\n'

printf '%03o\n' 9786
printf '\\23072\n' isn't going to work.

printf '\u0x263a\n' works, though.

Again, look at the Wooledge BashFAQ.

So in summary, this bug report is in error, the current behaviour is required by POSIX, and there are ways to do what you want in pure bash, if not pure POSIX. It appears POSIX does not specify the \u or \U escape sequences.

Peter Cordes <pcordes>
Thu 12 Aug 2004 07:57:35 PM UTC, comment #1:

I kinda fixed it :-) I'm just a wannabe-hacker trying to learn my ropes right. Please let me know if what I did is wrong.

G. Vamsee Krishna <vamsee>
Thu 08 Apr 2004 11:31:32 AM UTC, original submission:

Following the bash man page, printf "%c" <argument> should
behave as used with printf(3), namely accept a numeric
argument and then interprete it as the ASCII value of a
single character.
printf "%c" 65
is supposed to send the letter "A" to stdout. In fact, "6"
is seen. BTW, the coreutils printf(1) behaves wrong, too.




(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:

Attached Files
file #3867:  printf.patch added by vamsee (1KiB - text/x-patch - Patch for printf.)


Depends on the following items: None found

Items that depend on this one: None found


Carbon-Copy List
  • -email is unavailable- added by chet (Updated the item)
  • -email is unavailable- added by dualbus (Posted a comment)
  • -email is unavailable- added by pcordes (Posted a comment)

    Do you think this task is very important?
    If so, you can add your encouragement to it.
    This task has 0 encouragements so far.

    Only logged-in users can vote.


    Please enter the title of George Orwell's famous dystopian book (it's a date):



    Follow 2 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2015-11-12 chet StatusNone => Done
    2004-08-12 vamsee Attached File- => Added printf.patch, #57

    Back to the top

    Powered by Savane 3.3