Differences between revisions 3 and 17 (spanning 14 versions)
Revision 3 as of 2007-10-03 19:57:28
Size: 2121
Editor: GreyCat
Comment: add unhex()
Revision 17 as of 2009-10-20 04:10:16
Size: 1902
Editor: dsl-207-112-125-93
Comment: Minor formatting
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
[[Anchor(faq71)]] <<Anchor(faq71)>>
Line 3: Line 4:

This task is quite easy while using the {{{printf}}} builtin. You can either write two simple functions as shown below or use the plain {{{printf}}} constructions alone.
If you have a known octal or hexadecimal value (at script-writing time), you can just use `printf`:
Line 7: Line 7:
   # POSIX
   printf '\x27\047\n'
}}}
This prints two literal ' characters (27 is the hexadecimal ASCII value of the character, and 47 is the octal value) and a newline.

If you need to convert characters (or numeric ASCII values) that are not known in advance (i.e., in variables), you can use something a little more complicated:

{{{
   # POSIX
Line 9: Line 18:
 
Line 13: Line 22:
        #Another version doing the octal conversion with arithmetic
   # faster as it avoids a subshell
  chr () {
    printf \\$(($1/64*100+$1%64/8*10+$1%8))
   }
Line 21: Line 36:
   hex() {     hex() {
Line 30: Line 45:
 
Line 34: Line 49:
The {{{ord}}} function above is quite tricky.
Line 35: Line 51:
The {{{ord}}} function above is quite tricky. It can be re-written in several other ways (use that one that will best suite your coding style or your actual needs).

 ''Q:
Tricky? Rather, it's using a feature that I can't find documented anywhere -- putting a single quote in front of an integer. Neat effect, but how on '''earth''' did you find out about it? Source diving? -- GreyCat''

 ''A:
It validates The Single Unix Specification: "If the leading character is a single-quote or double-quote, the value shall be the numeric value in the underlying codeset of the character following the single-quote or double-quote." (see [http://www.opengroup.org/onlinepubs/009695399/utilities/printf.html printf()] to know more) -- mjf''

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

Or:

{{{
   ord() {
     printf '%d' \'$1\'
   }
}}}

Or, rather:

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

Etc. All of the above {{{ord}}} functions should work properly. Which one you choose highly depends on particular situation.



There is also an alternative when printing characters by their ascii value that is using escape sequences like:
{{{
   echo $'\x27'
}}}
which prints a literal ' (there 27 is the hexadecimal ascii value of the character).
 . ''Tricky? Rather, it's using a feature that I can't find documented anywhere -- putting a single quote in front of an integer. Neat effect, but how on '''earth''' did you find out about it? Source diving? -- GreyCat''
 . ''It validates The Single Unix Specification: "If the leading character is a single-quote or double-quote, the value shall be the numeric value in the underlying codeset of the character following the single-quote or double-quote." (see [[http://www.opengroup.org/onlinepubs/009695399/utilities/printf.html|printf()]] to know more) -- mjf''

How do I convert an ASCII character to its decimal (or hexadecimal) value and back?

If you have a known octal or hexadecimal value (at script-writing time), you can just use printf:

   # POSIX
   printf '\x27\047\n'

This prints two literal ' characters (27 is the hexadecimal ASCII value of the character, and 47 is the octal value) and a newline.

If you need to convert characters (or numeric ASCII values) that are not known in advance (i.e., in variables), you can use something a little more complicated:

   # POSIX
   # chr() - converts decimal value to its ASCII character representation
   # ord() - converts ASCII character to its decimal value

   chr() {
     printf \\$(printf '%03o' $1)
   }
  
   #Another version doing the octal conversion with arithmetic 
   # faster as it avoids a subshell
  chr () {
    printf \\$(($1/64*100+$1%64/8*10+$1%8))
   } 

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

   # hex() - converts ASCII character to a hexadecimal value
   # unhex() - converts a hexadecimal value to an ASCII character

   hex() {
      printf '%x' "'$1"
   }

   unhex() {
      printf \\x"$1"
   }

   # examples:

   chr $(ord A)    # -> A
   ord $(chr 65)   # -> 65

The ord function above is quite tricky.

  • Tricky? Rather, it's using a feature that I can't find documented anywhere -- putting a single quote in front of an integer. Neat effect, but how on earth did you find out about it? Source diving? -- GreyCat

  • It validates The Single Unix Specification: "If the leading character is a single-quote or double-quote, the value shall be the numeric value in the underlying codeset of the character following the single-quote or double-quote." (see printf() to know more) -- mjf

BashFAQ/071 (last edited 2021-02-08 16:03:51 by GreyCat)