Bash Menu: Return to menu after selection made and

2019-08-27 16:37发布

I've got a bash script that writes to a file. at the end of the script I want to display a menu, with line numbers - and have the user be able to select 1 or 2, (etc. up to the number of lines in the file) then have it execute that line.

Up to here is perfect.

However, after the line is executed (say for example it displays another file.) I'd like to return to the menu and let the user select another number. Including zero for exiting the menu.

Once the menu is displayed I have the following. (dumpline being the line of the file read)

     dresult=`sed -n "$dumpline"p "$PWD"/"$myday1"_"$myjob".txt`
     $dresult

But right now - after running the variable $dresult - it exits the shell (where instead I'd like the menu displayed.

Any thoughts?

thank you in advance.

标签: bash menu sed
3条回答
Explosion°爆炸
2楼-- · 2019-08-27 17:07

I think, you need something like a loop. Here is a small skelleton for executing a selected line from file:

#!/bin/bash

dumpfile="bla.txt"

echo "ls
echo 'hello'" > ${dumpfile}

function do_action {
    line="$( sed -n "${1},1p" "$dumpfile" )"
    (
        eval "${line}"
    )
}

cat -n $dumpfile
nr=$( cat "${dumpfile}" | wc -l )
PS3="select line nr or nr for QUIT: "
select ACTION in $( seq "$nr" ) QUIT
do
    case $ACTION in
        QUIT) echo "exit" ; break ;; #EXIT
        *) do_action "$ACTION" ;;
    esac
done

But be aware of the following:

  • Using eval might be not allways be a good idea (escaping is hard). Sometimes $line should be sufficient.
  • Using a subshell prevents changing variables by executing a line of the file. It also does prevent exiting the script from lines that do normally exits a shell.
查看更多
欢心
3楼-- · 2019-08-27 17:26

Here's another way to do a menu which relies on cat having the ability to number the lines of a file (some versions of cat may not have that - see the second example if this is the case). Both examples are for a simple four-item menu:

while [[ 1 ]]
do
    cat -n menufile
    read -p "Make a selection " choice
    case $choice in 
        1|2) 
           echo "A or B"
           ;;
        3) 
           echo "C"
           ;;
        4) 
           break
           ;;
        *) 
           echo "Invalid choice"
           ;;
    esac
done

This doesn't require cat -n:

saveIFS="$IFS"
IFS=$'\n'
read -d '' -a menuarray < menufile
IFS="$saveIFS"

for (( i=0; i<${#menuarray[@]}; i++ ))
do
    menu=$menu"$(($i+1))) ${menuarray[i]}"$'\n'
done

while [[ 1 ]]
do
    echo "$menu"
    read -p "Make a selection " choice
    case $choice in 
        1|2) 
           echo "A or B"
           ;;
        3) 
           echo "C"
           ;;
        4) 
           break
           ;;
        *) 
           echo "Invalid choice"
           ;;
    esac
done
查看更多
虎瘦雄心在
4楼-- · 2019-08-27 17:30

My comments on dz's answer are too long for a comment, so I'm posting them here:

Using seq with select would make a redundant-looking menu, with no correlation between it and the display of the lines in $dumpfile:

ls
echo 'hello'

1) 1
2) 2
etc.

You could do something like this instead:

saveIFS=$IFS
IFS=$'\n'
menu=$(< $dumpfile)
PS3="Make a selection: "
select ACTION in $menu QUIT
do
    IFS=$saveIFS
    case ...
查看更多
登录 后发表回答