Unix Shell Script: With Menu Option

I am attempting to create a shell script with the following capaciblities:

  1. Listed options to choice from
  2. Use to perform awk statements
  3. Print a report with the awk results

My questions are

  1. How do I select more than one file for option #5 and #6
  2. How to I create an output file for each option of 5 and 6
  3. Is it better to use case statements, if so why
  4. I am receiving the following arrow message on line #21.
    '/menu_script.sh: line 21: syntax error near unexpected token `in
    '/menu_script.sh: line 21: ` case "$yourch" in

Below is the script:

# Script to create menus and take action according to that selected menu item.
#
#
while :
do
clear
echo "----------------------------------------------"
echo " * * * * * * * Main Menu * * * * * * * * * * "
echo "----------------------------------------------"
echo "[1] Show Today's date/time"
echo "[2] Show files in current directory"
echo "[3] Show calendar"
echo "[4] Start editor to write letters"
echo "[5] Show IP's scanned by Nessus"
echo "[6] Produce a Tabular Nessus Report"
echo "[7] Produce a non-scan Tabular Nessus Report"
echo "[8] Exit/stop"
echo "----------------------------------------------"
echo -n "Enter your menu choice [1-5]:"
read yourch
case $yourch in
1) echo "Today is 'date' , press a key. . ." ; read ;;
2) echo "Files in 'pwd'" ; ls -l ; ech "Press a key. . ." ; read ;;
3) cal ; echo "Press a key. . ." ; read ;;
4) vi ;;
5) echo "Enter your NBE file(s): \c"; read FNAME; cat "$FNAME" | grep results |
awk -F"|" '{print $3}' | sort | uniq ;;
6) echo "Enter your NBE file(s): \c"; read FNAME; cat "$FNAME" |
awk -F"|" '$1 == "results" {gsub (/\n/,"",$7};
printf "%s\t%s\t%s\t%s\t%s\n", $3,$4,$5,$6,$7}' > rawresults.txt
7) echo "Enter your NBE file(s): \c"; read FNAME; cat "$FNAME" | awk -F"|"
'$1 != "results" {gsub (/\n/,"",$7); printf "%s\t%s\t%s\n", $1,$2,$3,&$7} > non_results.txt
8) exit 0 ;;
*) echo "Opps!!! Please select choice 1,2,3,4,5,6,7 or 8";
echo "Press a key. . ." ; read ;;
esac
done

# Script to create menus and take action according to that selected menu item.
#
#
while :
  do
  clear
  echo "----------------------------------------------"
  echo " * * * * * * * Main Menu * * * * * * * * * * "
  echo "----------------------------------------------"
  echo "[1] Show Today's date/time"
  echo "[2] Show files in current directory"
  echo "[3] Show calendar"
  echo "[4] Start editor to write letters"
  echo "[5] Show IP's scanned by Nessus"
  echo "[6] Produce a Tabular Nessus Report"
  echo "[7] Produce a non-scan Tabular Nessus Report"
  echo "[8] Exit/stop"
  echo "----------------------------------------------"
  echo -n "Enter your menu choice [1-5]:"
  read yourch
  case $yourch in
    1) echo "Today is 'date' , press a key. . ." ; read -n 1;;
    2) echo "Files in 'pwd'" ; ls -l ; echo "Press a key. . ." ; read -n 1 ;;
    3) cal ; echo "Press a key. . ." ; read -n 1 ;;
    4) vi ;;
    5) echo "Enter your NBE file(s): \c"
       read FNAME
       for F in $FNAME; do
         awk -F"|" '/results/ {print $3}' "$F" | sort | uniq
       done
       ;;
    6) echo "Enter your NBE file(s): \c"
       read FNAME
       for F in $FNAME; do
         cat "$F" | awk -F"|" '$1 == "results" {gsub (/\n/,"",$7} printf {"%s\t%s\t%s\t%s\t%s\n", $3,$4,$5,$6,$7}' > ${F}_rawresults.txt
       done
       ;;
    7) echo "Enter your NBE file(s): \c";
       read FNAME; cat "$FNAME" | awk -F"|" '$1 != "results" {gsub (/\n/,"",$7); printf "%s\t%s\t%s\n", $1,$2,$3,&$7}' > non_results.txt
       ;;
    8) exit 0
       ;;
    *) echo "Opps!!! Please select choice 1,2,3,4,5,6,7 or 8"
       echo "Press a key. . ."
       read -n 1
       ;;
  esac
done

You have a typo on option 2: ech should be echo. You didn't terminate 7) and 6 correctly, also on option 7) printf "%s\t%s\t%s\n", $1,$2,$3,&$7} is missing a {. I've also added option "-n 1" to most read command so it'll accept any key, not just the return carriage. One more thought, most of the time you can use just awk to replace the combination (piping) of cat/grep/awk, as you can see in option 5.

Actually since you're splitting FNAME on whitespace, you might as well pass the list of file names to awk directly, and avoid the for loop.

awk -F"|" '/results/ {print $3}' $FNAME | sort -u

(Note also the use of sort -u instead of sort | uniq)

This is one of the relatively rare scenarios where you don't want double quotes around the variable name, since you want the shell to split it on whitespace into multiple file names. Of course, it's tricky to pass in a file name with a space, although I guess you could figure it out if you really wanted to. (Update: guess you can't, actually.)

Thanks for your help thus far. I am still receiving the error:

  1. I am receiving the following arrow message on line #21.
    '/menu_script.sh: line 21: syntax error near unexpected token `in
    '/menu_script.sh: line 21: ` case "$yourch" in

Any suggestions?

Read the error message.

You have a backtick (`) where there shouldn't be one; remove it.

Actually the error message doesn't correlate with the posted script. I'm guessing it's being interpreted by the wrong shell; try adding an explicit #!/bin/sh as the first line to make sure it's not passed to (say) csh.

That's not unusual. But irrelevant. The error message tells what's wrong in the script that is being executed.

If it were being passed to csh it wouldn't get as far as it did.

And it wouldn't be interpreted by csh unless it is called from csh (e.g., as the user's command-line shell), or called explicitly as an argument to csh.

Check this :http://www.unix.com/shell-programming-scripting/46475-interactive-menu.html

May helps you.

cfajohnson: You are right about the csh part -- I misremembered some part of Why do some scripts start with #! ... ?

Still, the error message doesn't really support the hypothesis of a superfluous backtick, IMHO; I'm guessing it's a problem of unpaired quotes or some such.

On the contrary, that's exactly what the error message does say:

The first line says there is an unexpected backtick; the second lists it.

Just plain "in" as a command produces the same error message for me. If you have something like

yourch="oops\"   # accidentally backslashed closing quote producing multi-line string
case "$yourch" in whatever

the error message is different, but I'm speculating that something along those lines might be the expanation, still.

I'm not saying there isn't a backquote too many somewhere, just that the backquote before the `in' seems to be part of the error message's formatting (but then the closing single quote is missing), at least the way it looks here, with bash.

Be that as it may, the original poster had better either post the code exactly as it is (for example, the double quotes around "$yourch" in the error message also don't match the posted code), or look closely for superfluous quotes of all kinds on his own.

My apologies. You are quite right. I was thrown off by the missing apostrophe.