Меню Bash: вернуться в меню после того, как выбор сделан и выполнен?

У меня есть bash-скрипт, который пишет в файл. в конце сценария я хочу отобразить меню с номерами строк, и пользователь сможет выбрать 1 или 2 (и т. д. до количества строк в файле), а затем выполнить эту строку.

До здесь идеально.

Однако после выполнения строки (скажем, например, она отображает другой файл). Я хотел бы вернуться в меню и позволить пользователю выбрать другой номер. В том числе ноль для выхода из меню.

После отображения меню у меня есть следующее. (dumpline — это строка прочитанного файла)

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

Но прямо сейчас - после запуска переменной $dresult - он выходит из оболочки (где вместо этого я бы хотел, чтобы отображалось меню.

есть идеи?

заранее спасибо.


person Chasester    schedule 02.11.2009    source источник
comment
Есть ли у вас цикл вокруг конструкции меню, так что после завершения первого действия меню снова отображается? Не могли бы вы опубликовать это?   -  person martin clayton    schedule 02.11.2009
comment
Я еще не знаю. он просто отображает строки файла. Но я как раз думал о настройке функций для выполнения работы.   -  person Chasester    schedule 02.11.2009


Ответы (3)


Я думаю, вам нужно что-то вроде цикла. Вот небольшой скелет для выполнения выбранной строки из файла:

#!/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

Но имейте в виду следующее:

  • Использование eval может быть не всегда хорошей идеей (убежать сложно). Иногда $line должно быть достаточно.
  • Использование подоболочки предотвращает изменение переменных путем выполнения строки файла. Это также предотвращает выход из сценария из строк, которые обычно выходят из оболочки.
person dz.    schedule 02.11.2009

Вот еще один способ сделать меню, основанное на том, что cat имеет возможность нумеровать строки файла (в некоторых версиях cat этого может не быть - см. второй пример, если это так). Оба примера относятся к простому меню из четырех пунктов:

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

Для этого не требуется 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
person Dennis Williamson    schedule 02.11.2009
comment
Спасибо, Денис. Я не могу получить к нему доступ, пока я не на работе. но я попробую, когда вернусь туда. Большое спасибо. - person Chasester; 03.11.2009

Мои комментарии к ответу dz слишком длинные для комментария, поэтому я публикую их здесь:

Использование seq с select сделало бы меню избыточным, без корреляции между ним и отображением строк в $dumpfile:

ls
echo 'hello'

1) 1
2) 2
etc.

Вместо этого вы можете сделать что-то вроде этого:

saveIFS=$IFS
IFS=$'\n'
menu=$(< $dumpfile)
PS3="Make a selection: "
select ACTION in $menu QUIT
do
    IFS=$saveIFS
    case ...
person Dennis Williamson    schedule 02.11.2009
comment
+1 за этот хороший трюк. Хотя я также вставляю строки в in satement, но, как и во встроенном for, у вас возникают проблемы с пробелами. Но изменение IFS помогает. - person dz.; 02.11.2009
comment
кажется, работает хорошо Деннис. Я просто удалил строку = часть. Однако один вопрос - как я могу вернуть его в меню после отображения пункта меню? - person Chasester; 02.11.2009
comment
Нашел! ) echo Нажмите Enter, чтобы снова увидеть меню! Продолжать ;; - person Chasester; 02.11.2009