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: NonePriority: 5 - Normal
Severity: 3 - NormalStatus: None
Privacy: PublicAssigned to: None
Originator Email: -unavailable-Open/Closed: Open
Operating System: None

Add a New Comment (Rich MarkupRich Markup):
   

You are not logged in

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

 

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

http://pubs.opengroup.org/onlinepubs/009695399/utilities/printf.html

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
char=A
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
http://mywiki.wooledge.org/BashFAQ/071 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"
9786

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'

but
printf '%03o\n' 9786
23072
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.
Thus,
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.

Regards,
kno.

Anonymous

 

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

Attach File(s):
   
   
Comment:
   

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

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -unavailable- added by pcordes (Posted a comment)
  •  

    Do you think this task is very important?
    If so, you can click here to 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):

     

     

    Follows 1 latest change.

    Date Changed By Updated Field Previous Value => Replaced By
    Thu 12 Aug 2004 07:57:35 PM UTCvamseeAttached File-=>Added printf.patch, #57

    Back to the top


    Powered by Savane 3.1-cleanup