LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - General (https://www.linuxquestions.org/questions/linux-general-1/)
-   -   How to make shell script wait for a particular key pressed in order to proceed? (https://www.linuxquestions.org/questions/linux-general-1/how-to-make-shell-script-wait-for-a-particular-key-pressed-in-order-to-proceed-785758/)

Caed Lucin 01-30-2010 01:06 AM

How to make shell script wait for a particular key pressed in order to proceed?
 
Hello,

This is a question for shell scripting. Uhmm i've been searching all over the internet for a way to let the user press a particular key let's say 'y' without the user having to press [Enter] as confirmationfor yes, this would then run another function.

like say..


Quote:

Book Inventory Summary Report:-

Title, Author, Price
______________________________
StarWars EP1, G.Lucas, $49.59
Harry Potter, Rowling, $45.98
The Matrix, Mr. Smith, $53.98


Press 'y' to make a copy of this result into a file or 'n' to return to the main menu..

I understand the "press any key to continue" would go something like

Code:

read -sn 1 -p "Press any key to continue.."
But i try many different ways of getting the "press a particular key" function, and none of them works. Any help would be much appreciated! Thanks you! :)

catkin 01-30-2010 01:18 AM

Try something like
Code:

prompt='Press n for no or y for yes '
echo -n "$prompt"
while read -n1 char
do
    case $char in
        n | N )
            # <commands as required>
            break
            ;;
        y | Y )
            # <commands as required>
            break
            ;;
        * )
            echo -ne "\nInvalid character '$char' entered. $prompt"
    esac
done


Caed Lucin 01-30-2010 01:44 AM

Quote:

Originally Posted by catkin (Post 3845719)
Try something like
Code:

prompt='Press n for no or y for yes '
echo -n "$prompt"
while read -n1 char
do
    case $char in
        n | N )
            # <commands as required>
            break
            ;;
        y | Y )
            # <commands as required>
            break
            ;;
        * )
            echo -ne "\nInvalid character '$char' entered. $prompt"
    esac
done


Wow! Thank you very much catkin! That worked! But here's the problem, when i press the arrow keys instead of any other keys, my next input for main menu choice would go haywire.

as my program's menu structure goes like this..

Book Inventory Program
1) Add book
2) Remove book
3) Update book
4) Search book
5) Process book sold
6) Inventory Summary Report <<-- This is where the "press a particular key" thing is implemented.
7) Quit


Anyway below is my function just in case you guys need to see it. It's pretty messy and i'm not sure if there's any way i could save the awk printout into a file without having to copy the whole awk command again for file saving process. :)

Code:

function inventory_summary_report
{
        echo "##########################"
    echo " INVENTORY SUMMARY REPORT"
        echo "##########################"

        echo ""
        cat $FILENAME | sort | awk -F':' 'BEGIN {
                                format1="%-45s %-20s %-20s %-20s %-20s %-20s\n"
                                format2="%-45s %-20s $%-20.2f %-20d %-20d $%.2f\n"
                                printf (format1, "Title", "Author", "Price", "Qty Avail", "Qty Sold", "Total Sales")
                                printf  "_____________________________________________________________________________________________________________________________________________\n"}
                                { printf (format2, $1, $2, $3, $4, $5, $3*$5); }'
        echo ""
        echo "Press 'Y' to make a copy of the inventory summary report or any other key to return to main menu.."

        while read -sn1 keyPressed
        do
                case $keyPressed in
                        y | Y )                cat $FILENAME | sort | awk -F':' 'BEGIN {
                                format1="%-45s %-20s %-20s %-20s %-20s %-20s\n"
                                format2="%-45s %-20s $%-20.2f %-20d %-20d $%.2f\n"
                                printf (format1, "Title", "Author", "Price", "Qty Avail", "Qty Sold", "Total Sales")
                                printf  "_____________________________________________________________________________________________________________________________________________\n"}
                                { printf (format2, $1, $2, $3, $4, $5, $3*$5); }' >> Hello.txt;
                                                echo "Returning to main menu.." ;
                                                break;;
                        n | N )                echo "Returning to main menu.." ; return ; break ;;
                        * )                        tput setf 4 ; echo "Please press either 'y' or 'n'.."; tput setf 0 ;;
                esac
        done
}


catkin 01-30-2010 03:44 AM

Quote:

Originally Posted by Caed Lucin (Post 3845737)
But here's the problem, when i press the arrow keys instead of any other keys, my next input for main menu choice would go haywire.

True :(

Unfortunately bash does not have a non-blocking read facility so there's no way to empty the terminal input (keyboard) buffer. It could be done by writing a custom "external command" (that's bash-speak) as mentioned here.

A version of bash later than the 3.1.7 used for testing introduced fractions of a second on read's -t option. GNU Bash Reference says this about read: "-t timeout Cause read to time out and return failure if a complete line of input is not read within timeout seconds. timeout may be a decimal number with a fractional portion following the decimal point."

This could be used with a low timeout value to approximate a non-blocking read, something like this to go at the top of the * case code above (it's a bit ugly, maybe putting a string in a variable called char!)
Code:

while read -t '0.01' -n1 buf
do
    char="$char$buf"
done


Caed Lucin 01-31-2010 12:15 AM

Ahhh i see, well it didn't work out the way i hope it would, but thank you very much for your help catkin! :)

I'll still use the case thing but will keep my fingers crossed hoping the the person assessing my assignment ain't gonna hit the arrow keys. hahaha.

trey85stang 01-31-2010 06:08 PM

small change to catkins code...

Code:

while true
do 
  prompt='Press n for no or y for yes '
  echo -n "$prompt"
  read -n1 char
  case "$char" in
      [Nn])
          # <commands as required>
          break
          ;;
      [Yy])
          # <commands as required>
          break
          ;;
      *)
          echo -ne "\nInvalid character '$char' entered.\nPlease try again"
          continue
    esac
done

I like brackets better then piping n case so I just changed them.. either way works. This will put you in a loop, so the question is re-asked if YyNn is not selected.


All times are GMT -5. The time now is 04:38 PM.