1

I am using read for user input to perform some operation. The selector uses a two character test to print the appropriate information, without requiring the user to press ENTER after his input. Would it be possible to accept the q value to exit, because it is not composed of a two character selector.

  local done="false"
  while [ "$done" != "true" ]
  do
    echo ; read -n 2 lsk
    case $lsk in
     "1L")
        echo "$navaid_vscal"
        echo -e "$tacrgm"
        ;;
     q)
        done="true"  # ends while loop
        echo -n "$sgr"
        ;;
     *)
        ## repeats while do
        ;;
    esac
  done

2 Answers 2

2

I don't believe the bash read built-in has that functionality. However you can implement a custom read command or function to achieve that.

For example, you can use this function:

read_or_quit(){
x=0;
while ((++x<=2)); do 
   read -n 1

   if [[ $REPLY = q ]]; then 
      echo q
      break
   else 
     echo -n "$REPLY"
   fi
done ; 
echo

# I thought that printing `echo` to `stdout` would
# append a new line which might break the `case` 
# functionality.
# echo >&2
}

And you can call the function by using $(read_or_quit) in your code:

local done="false"
  while [ "$done" != "true" ]
  do
    lsk=$(read_or_quit)
    case $lsk in
     "1L")
        echo "$navaid_vscal"
        echo -e "$tacrgm"
        ;;
     q)
        done="true"  # ends while loop
        echo -n "$sgr"
        ;;
     *)
        ## repeats while do
        ;;
    esac
  done
8
  • What is the purpose of echo >&2 ? Commented Jan 27, 2023 at 4:57
  • @konmi For printing a break line to stderr. It's not necessary at all, you can simply use echo or just remove it. I used echo at the end of the function to avoid using this one after you call the function: lsk=$(read_or_quit). Commented Jan 27, 2023 at 5:06
  • What does it mean "to avoid using this one", what does "the one" refer to? Commented Jan 27, 2023 at 5:08
  • @konmi I meant echo, to avoid using echo. If you removed the echo a break line will not be printed. You can remove it and the code will work but the output might be ugly Commented Jan 27, 2023 at 5:13
  • Thank you for the clarification. I would have to keep it, although printing to stderr seems unimportant in my case. Why would you elect to send it to stderr ? Commented Jan 27, 2023 at 5:22
1

Split the read into an initial read (which leaves early when q is entered) and a subsequent one for the second character (I'll call them ch1 and ch2):

local done=false
until "$done"
do
    echo
    read -n 1 ch1
    if [ ch1 = q ]
    then
        printf %s "$sgr"  # More portable than echo -n
        break
    fi
    read -n 1 ch2
    case "$ch1$ch2" in
        1L)
            echo "$navaid_vscal"
            echo -e "$tacrgm"  # portability problem here!
            ;;
        *)
            ## repeats while do
            ;;
    esac
done

Obviously, the loop can be while true since nothing now sets done, but perhaps you'll need that in one of the case blocks, so I kept it. (I did change the string equality test to just running $done as a command, for simplicity)

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.