Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

bash scripting - read single keystroke including special keys enter and space

Not sure if I should put this on stackoverflow or unix.stackexchange but I found some similar questions here, so here it goes.

I'm trying to create a script to be called by .bashrc that allows me to select one of two options based on a single keystroke. That wouldn't be hard normally but I want the two keys corresponding to the two options to be space and enter.

Here's what I got so far:

#!/bin/bash

SELECT=""
while [[ "$SELECT" != $'\x0a' && "$SELECT" != $'\x20' ]]; do
    echo "Select session type:"
    echo "Press <Enter> to do foo"
    echo "Press <Space> to do bar"
    read -s -N 1 SELECT
    echo "Debug/$SELECT/${#SELECT}"
    [[ "$SELECT" == $'\x0a' ]] && echo "enter" # do foo
    [[ "$SELECT" == $'\x20' ]] && echo "space" # do bar
done

The following output is what I get if I press enter, space, backspace and x:

:~$ bin/sessionSelect.sh
Select session type:
Press <Enter> to start/resume a screen session
Press <Space> for a regular ssh session
Debug//0
Select session type:
Press <Enter> to start/resume a screen session
Press <Space> for a regular ssh session
Debug//0
Select session type:
Press <Enter> to start/resume a screen session
Press <Space> for a regular ssh session
Debug//1
Select session type:
Press <Enter> to start/resume a screen session
Press <Space> for a regular ssh session
Debug/x/1

So both enter and space result in an empty SELECT. No way to distinguish the two. I tried to add -d 'D' to the read options, but that didn't help. Maybe someone can point me in the right direction.

The bash version would be 4.2 btw.

like image 278
a.peganz Avatar asked Apr 03 '14 15:04

a.peganz


People also ask

What does [- Z $1 mean in bash?

$1 means an input argument and -z means non-defined or empty. You're testing whether an input argument to the script was defined when running the script. Follow this answer to receive notifications.

What is $@ in bash script?

bash [filename] runs the commands saved in a file. $@ refers to all of a shell script's command-line arguments. $1 , $2 , etc., refer to the first command-line argument, the second command-line argument, etc. Place variables in quotes if the values might have spaces in them.

What does #$ mean in bash?

#$ does "nothing", as # is starting comment and everything behind it on the same line is ignored (with the notable exception of the "shebang"). $# prints the number of arguments passed to a shell script (like $* prints all arguments). Follow this answer to receive notifications. edited Jul 9 at 13:55.

Which bash command is used to read input from keyboard?

To read the Bash user input, we use the built-in Bash command called read. It takes input from the user and assigns it to the variable.


3 Answers

Try setting the read delimiter to an empty string then check the builtin $REPLY variable:

read -d'' -s -n1

For some reason I couldn't get it to work specifying a variable.

like image 192
Cole Tierney Avatar answered Oct 17 '22 06:10

Cole Tierney


#!/bin/bash
SELECT=""
# prevent parsing of the input line
IFS=''
while [[ "$SELECT" != $'\x0a' && "$SELECT" != $'\x20' ]]; do
  echo "Select session type:"
  echo "Press <Enter> to do foo"
  echo "Press <Space> to do bar"
  read -s -N 1 SELECT
  echo "Debug/$SELECT/${#SELECT}"
  [[ "$SELECT" == $'\x0a' ]] && echo "enter" # do foo
  [[ "$SELECT" == $'\x20' ]] && echo "space" # do bar
done
like image 29
Andrey Avatar answered Oct 17 '22 08:10

Andrey


There are a couple of things about read that are relevant here:

  • It reads a single line
  • The line is split into fields as with word splitting

Since you're reading one character, it implies that entering Enter would result into an empty variable.

Moreover, by default rules for word splitting, entering Space would also result into an empty variable. The good news is that you could handle this part by setting IFS.

Change your read statement to:

IFS= read -s -n 1 SELECT

and expect a null string instead of $'\x0a' when entering Enter.

like image 2
devnull Avatar answered Oct 17 '22 06:10

devnull