Catching a carriage return in bash

23 October 2006   2 comments   Linux

Mind That Age!

This blog post is 11 years old! Most likely, its content is outdated. Especially if it's technical.

Powered by Fusion×

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!";
   echo "|$Q|"; # for debugging what Q is

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?


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

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

The get_key function is defined like this:

   [ -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 ]
         stty -echo -icanon time $(( $_TMOUT * 10 )) min ${dd_min:-1}
         stty -echo -icanon min ${dd_min:-1}

   ## 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'" ;;
   [ -t 0 ] && stty "$_STTY"  ## reset terminal
   [ -n "$_KEY" ]  ## Succeed if a key has been entered (not timed out)


Thank you Ivo! That solved the problem! :)


Ivo van der Wijk
In case anyone's looking for the answer:
$ x="
$ if [ "$x" = $'\n' ]; then echo "newline"; fi

m() {
cat << EOP

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

until [[ $k == [qQ] ]]; do
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" ;;
Thank you for posting a comment

Your email will never ever be published

Related posts

New domain name 20 October 2006
Sending HTML emails in Zope 26 October 2006
Related by Keyword:
A neat trick to zip a git repo with a version number 01 September 2017
And bash basics 16 October 2015
set -ex - The most useful bash trick of the year 31 August 2014
Highlighted code syntax in Keynote 30 August 2014
How I do deployments 16 December 2013
Related by Text:
Geeking with Eterm and Tkinter 09 February 2006
Read in passwords with bash 25 March 2005
FacebookStatusUpdater 07 June 2007
And bash basics 16 October 2015
SVN + ./todo + crontab 20 May 2006