12

I'm trying to write a shell script which asks for an ASCII character in the range A-Z or a-z and returns its equivalent numerical value. For example, the output might look like the following:

scarlet$ Please type a character between A and Z or between a and z:
scarlet$ A       
scarlet$ The decimal value of A is: 65 

My attempt:

#!/bin/bash
echo Enter a letter:
read A
echo -n ${A} | od -i | head -1 | cut -b 10- | tr -d " "
xenoterracide
  • 57,918
  • 74
  • 184
  • 250
Host Post
  • 207
  • 3
  • 4
  • 7
  • I edited out your second question since it was unrelated; you should [post it separately](http://unix.stackexchange.com/questions/ask) (you can get the original text [here](http://unix.stackexchange.com/revisions/cb4d5704-7ac2-41a9-92ed-2578e8b0d8f9/view-source)) – Michael Mrozek Mar 18 '11 at 02:19
  • Your example works for me. Can you paste output showing what happens and describe what the error is? Does `echo -n A` do what you expect? If not, try `printf` instead. Does `od -i` do what you expect? If not, try `od -t d1`. – Mikel Mar 18 '11 at 03:10
  • 1
    I tried od -t d1 worked great... Thanks – Host Post Mar 19 '11 at 12:11

7 Answers7

13

POSIX:

$ printf %d\\n \'a
97

It also works with non-ASCII characters in bash 4.0 and later and in zsh:

$ printf %x\\n \'あ
3042

You can also use recode ..dump to see hexadecimal code points:

$ printf aあ|recode ..dump
UCS2   Mne   Description

0061   a     latin small letter a
3042   a5    hiragana letter a
Lri
  • 5,143
  • 2
  • 27
  • 20
  • 2
    To make it a little bit less "obscure", one may also use e.g. `A=a ; printf '%d\n' "'$A'"` and on ksh something like `A=a; integer N=$(("'$A'")); print $N` (print or printf is not needed). – jelmd Nov 12 '17 at 17:03
11

POSIX: printf a | od -A n -t d1

Perl: perl -e 'print ord($ARGV[0])' a

Perl, coping with UTF-8 if in a UTF-8 locale: perl -C255 -e 'print ord($ARGV[0])' œ

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
3

Maybe:

#!/bin/bash

echo -n "Enter a letter:"
read A
echo ${A}|od -t d1|awk '{printf "%s",$2}';echo

Cheers

D4RIO
  • 1,586
  • 1
  • 11
  • 19
1

A od-less solution, just bash, and just lowercase, so far. z is the character searched for, here s as search. i=97 because ascii(a)=97. The rest is obvious.

z=s 
i=97
for c in {a..z}
do 
    [ "$c" = "$z" ] && echo $i && break || ((i+=1))
done

You may put it into a single line of course. Here are some semmicolons: ;;;;; (should be enough)

user unknown
  • 10,267
  • 3
  • 35
  • 58
0

Try od -t d1 if you have it. The other output formats are quite weird.

You also don't need head and cut, for example:

printf "A" | od -t d1 | read addr num && echo $num
Mikel
  • 56,387
  • 13
  • 130
  • 149
0
# Get one character per loop, until the user presses <Enter>
while true ; do 
    read -n 1 c
    (( ${#c} == 0 )) && break # Exit the loop. Input length is 0  
                              # ie. The user has pressed Enter
    #
    if [   \( ! "$c" \< "a" -a  ! "$c" \> "z" \) \
        -o \( ! "$c" \< "A" -a  ! "$c" \> "Z" \) ]
    then
        val=($(ascii -s $c)) # build an array of ascii info for this char 
        echo " ... The decimal value of $c is: ${val[1]}"
    else
        echo -n  $'\r \r' # overwrite the invalid character
    fi 
done
Peter.O
  • 32,426
  • 28
  • 115
  • 163
0

If you just want a program that does this and you're not doing this as an exercise then there's a program called ascii that does this. Your distro may offer it as a package already, if not get it from http://www.catb.org/~esr/ascii/.

bahamat
  • 38,658
  • 4
  • 70
  • 103