Catching a carriage return in bash


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

Show all 3 comments
 
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.