11

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 " "
3
  • I edited out your second question since it was unrelated; you should post it separately (you can get the original text here) – Michael Mrozek Mar 18 '11 at 2: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 3:10
  • 1
    I tried od -t d1 worked great... Thanks – Host Post Mar 19 '11 at 12:11
8

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])' œ

8

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
1
  • 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
3

Maybe:

#!/bin/bash

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

Cheers

3
  • I would just use awk, rather than nawk. This is pretty standard to any awk version. – asoundmove Mar 18 '11 at 3:47
  • Edited, is my habit of using 'nawk' since i've not awk at work – D4RIO Mar 18 '11 at 11:36
  • yes, your solution worked for me too .. thanks – Host Post Mar 19 '11 at 12:14
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)

3
  • I tested the above code .. but it didn't work for me .. I got a message saying " i+=1 " is not found! – Host Post Mar 19 '11 at 18:19
  • This works in bash. You may need i=$((i+1)) instead. – user unknown Mar 19 '11 at 18:49
  • In one line and with reading a key from the keyboard: read char; i=97; for c in {a..z}; do [ "$c" = "$char" ] && echo $i && break || ((i+=1)); done – erik Aug 30 '13 at 21:33
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
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/.

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
0

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.