Kung Fu Kung Fu

Fujian White Crane Kung Fu

Zope Zope

What I have and am doing with Zope

Photos Photos

Photoalbum, both old and new.

Receptsamlingen Receptsamlingen

In Swedish only. About my "Collection of Recipes" website.

Contact me Contact me

My contact details and how to contact me.

  Mobile version of this page Mobile version of this page


 

Catching a carriage return in bash

stty, carriage return, bash, syntax, bash syntax, linebreak

23rd of October 2006

I'm not a bash expert. Now I need some help with some bash syntax.

I copied a function called get_key which takes a 1 character length string from the stty input and assigns it to a variable. It's nifty because I can prompt something like this:

 Select task:
 1 - Task XYZ
 2 - Task F19
 3 - Task 123
 q - quit

So far so good. What I now want to do is to introduce a possible default. If you just hit enter the variable becomes a carriage return I think. If that's the case I have some other stuff that will kick in and find choose a default value. Here's the code:

 echo "Enter 1, 2, 3, q or just hit Enter";
 get_key Q; # assigns one character to variable Q
 if [ "$Q" = "\n" ]; then
    echo "Q was blank!";
 else
    echo "|$Q|"; # for debugging what Q is
 fi

The problem is that when I run this it never prints "Q was blank!". Here's the output when I just hit the Enter key when it runs:

 Enter 1, 2, 3, q or just hit Enter

 |
 |

Is the syntax not right? How do I compare if a variable is just a linkbreak/carriage return?

UPDATE

It's quite clear that my get_key function must do something strange. This little script will print "is" when you run it:

 Q="\n";
 if [ "$Q" = "\n" ]; then
    echo "is";
 fi

The get_key function is defined like this:

 get_key()
{
    [ -t 0 ] && {  ## Check whether input is coming from a terminal
        [ -z "$_STTY" ] && {
            _STTY=$(stty -g)  ## Store the current settings for later restoration
        }

        ## By default, the minimum number of keys that needs to be entered is 1
        ## This can be changed by setting the dd_min variable
        ## If the TMOUT variable is set greater than 0, the time-out is set to
        ## $TMOUT seconds
        if [ ${TMOUT:--1} -ge 0 ]
        then
          _TMOUT=$TMOUT
          stty -echo -icanon time $(( $_TMOUT * 10 )) min ${dd_min:-1}
        else
          stty -echo -icanon min ${dd_min:-1}
        fi
    }

    ## Read a key from the keyboard, using dd with a block size (bs) of 1.
    ## A period is appended, or command substitution will swallow a newline
    _KEY=$(dd bs=1 count=1 2>/dev/null; echo .)
    _KEY=${_KEY%?}  ## Remove the period

    ## If a variable has been given on the command line, assign the result to it
    [ -n "$1" ] &&
            ## quoting
            case $_KEY in
                 "'") eval "$1=\"'\"" ;;
                 *) eval "$1='$_KEY'" ;;
            esac
    [ -t 0 ] && stty "$_STTY"  ## reset terminal
    [ -n "$_KEY" ]  ## Succeed if a key has been entered (not timed out)
 }

UPDATE2

Thank you Ivo! That solved the problem! :)


Comment

Ivo van der Wijk - 24th October 2006  [«« Reply to this]
In case anyone's looking for the answer:
$ x="
"
$ if [ "$x" = $'\n' ]; then echo "newline"; fi
newline
Anonymous - 18th August 2008  [«« Reply to this]
#!/bin/bash

m() {
cat << EOP

Select task:
1 - Task XYZ
2 - Task F19
3 - Task 123
q - quit

EOP
}
k="1"
until [[ $k == [qQ] ]]; do
m
echo "enter 1, 2, 3, q or just hit Enter"
read -n 1 k
case $k in
1) echo "doing task XYZ" ;;
2) echo "doing task F19" ;;
3) echo "doing task 123" ;;
'') echo "Q was blank";;
q) echo "quitting now" && exit 0 ;;
*) echo "invalid key" ;;
esac
done
 
Name:
Email:
hide my email address.

Your email address will be encoded to prevent email-extraction spiders from reading it so you won't get spammed if you decide to show your email address.