linux - org - ubuntu mp3 tag editor




Как мне запросить ввод «Да/Нет/Отмена» в сценарии оболочки Linux? (18)

Да / Нет / Отменить

функция

#!/usr/bin/env bash
@confirm() {
  local message="$*"
  local result=''

  echo -n "> $message (Yes/No/Cancel) " >&2

  while [ -z "$result" ] ; do
    read -s -n 1 choice
    case "$choice" in
      y|Y ) result='Y' ;;
      n|N ) result='N' ;;
      c|C ) result='C' ;;
    esac
  done

  echo $result
}

использование

case $(@confirm 'Confirm?') in
  Y ) echo "Yes" ;;
  N ) echo "No" ;;
  C ) echo "Cancel" ;;
esac

Подтвердить с помощью чистого пользовательского ввода

функция

#!/usr/bin/env bash
@confirm() {
  local message="$*"
  local result=3

  echo -n "> $message (y/n) " >&2

  while [[ $result -gt 1 ]] ; do
    read -s -n 1 choice
    case "$choice" in
      y|Y ) result=0 ;;
      n|N ) result=1 ;;
    esac
  done

  return $result
}

использование

if @confirm 'Confirm?' ; then
  echo "Yes"
else
  echo "No"
fi

Я хочу приостановить ввод в сценарии оболочки и запросить пользователя для выбора. Стандартный вопрос «Да, нет или Отменить». Как это сделать в типичной подсказке bash?


По крайней мере пять ответов на один общий вопрос.

В зависимости от

  • posix совместимый: может работать на плохих системах с общими средами shell
  • bash специфический: использование так называемых базизмов

и если вы хотите

  • простой `` in line '' вопрос / ответ (общие решения)
  • довольно отформатированные интерфейсы, такие как ncurses или более графически, используя libgtk или libqt ...
  • использовать мощную способность чтения readline

1. Общие решения POSIX

Вы можете использовать команду read , а затем if ... then ... else :

echo -n "Is this a good question (y/n)? "
read answer

# if echo "$answer" | grep -iq "^y" ;then

if [ "$answer" != "${answer#[Yy]}" ] ;then
    echo Yes
else
    echo No
fi

(Спасибо комментарию Адама Каца : Заменил вышеприведенный тест тем, который более переносим и избегает одной вилки :)

POSIX, но одна ключевая функция

Но если вы не хотите, чтобы пользователь ударил Return , вы могли бы написать:

( Отредактировано: Как справедливо предлагает @JonathanLeffler, сохранение конфигурации stty может быть лучше, чем просто заставить их здравомыслящим .)

echo -n "Is this a good question (y/n)? "
old_stty_cfg=$(stty -g)
stty raw -echo ; answer=$(head -c 1) ; stty $old_stty_cfg # Careful playing with stty
if echo "$answer" | grep -iq "^y" ;then
    echo Yes
else
    echo No
fi

Примечание. Это было проверено под sh , bash , ksh , dash и busybox !

То же самое, но явно для y или n :

#/bin/sh
echo -n "Is this a good question (y/n)? "
old_stty_cfg=$(stty -g)
stty raw -echo
answer=$( while ! head -c 1 | grep -i '[ny]' ;do true ;done )
stty $old_stty_cfg
if echo "$answer" | grep -iq "^y" ;then
    echo Yes
else
    echo No
fi

Использование специальных инструментов

Существует множество инструментов, которые были созданы с использованием libncurses , libgtk , libqt или других графических библиотек. Например, используя whiptail :

if whiptail --yesno "Is this a good question" 20 60 ;then
    echo Yes
else
    echo No
fi

В зависимости от вашей системы вам может потребоваться заменить whiptail другим аналогичным инструментом:

dialog --yesno "Is this a good question" 20 60 && echo Yes

gdialog --yesno "Is this a good question" 20 60 && echo Yes

kdialog --yesno "Is this a good question" 20 60 && echo Yes

где 20 - высота диалогового окна в количестве строк, а 60 - ширина диалогового окна. Все эти инструменты имеют одинаковый синтаксис.

DIALOG=whiptail
if [ -x /usr/bin/gdialog ] ;then DIALOG=gdialog ; fi
if [ -x /usr/bin/xdialog ] ;then DIALOG=xdialog ; fi
...
$DIALOG --yesno ...

2. Специальные решения Bash

Основной метод

read -p "Is this a good question (y/n)? " answer
case ${answer:0:1} in
    y|Y )
        echo Yes
    ;;
    * )
        echo No
    ;;
esac

Я предпочитаю использовать case чтобы я мог даже проверить на yes | ja | si | oui yes | ja | si | oui yes | ja | si | oui при необходимости ...

в соответствии с одной ключевой функцией

В разделе bash мы можем указать длину предполагаемого ввода для команды read :

read -n 1 -p "Is this a good question (y/n)? " answer

В bash команда read принимает параметр таймаута , который может быть полезен.

read -t 3 -n 1 -p "Is this a good question (y/n)? " answer
[ -z "$answer" ] && answer="Yes"  # if 'yes' have to be default choice

Некоторые трюки для выделенных инструментов

Более сложные диалоговые окна, помимо простых yes - no целей:

dialog --menu "Is this a good question" 20 60 12 y Yes n No m Maybe

Индикатор:

dialog --gauge "Filling the tank" 20 60 0 < <(
    for i in {1..100};do
        printf "XXX\n%d\n%(%a %b %T)T progress: %d\nXXX\n" $i -1 $i
        sleep .033
    done
) 

Маленькая демонстрация:

#!/bin/sh
while true ;do
    [ -x "$(which ${DIALOG%% *})" ] || DIALOG=dialog
    DIALOG=$($DIALOG --menu "Which tool for next run?" 20 60 12 2>&1 \
            whiptail       "dialog boxes from shell scripts" >/dev/tty \
            dialog         "dialog boxes from shell with ncurses" \
            gdialog        "dialog boxes from shell with Gtk" \
            kdialog        "dialog boxes from shell with Kde" ) || exit
    clear;echo "Choosed: $DIALOG."
    for i in `seq 1 100`;do
        date +"`printf "XXX\n%d\n%%a %%b %%T progress: %d\nXXX\n" $i $i`"
        sleep .0125
      done | $DIALOG --gauge "Filling the tank" 20 60 0
    $DIALOG --infobox "This is a simple info box\n\nNo action required" 20 60
    sleep 3
    if $DIALOG --yesno  "Do you like this demo?" 20 60 ;then
        AnsYesNo=Yes; else AnsYesNo=No; fi
    AnsInput=$($DIALOG --inputbox "A text:" 20 60 "Text here..." 2>&1 >/dev/tty)
    AnsPass=$($DIALOG --passwordbox "A secret:" 20 60 "First..." 2>&1 >/dev/tty)
    $DIALOG --textbox /etc/motd 20 60
    AnsCkLst=$($DIALOG --checklist "Check some..." 20 60 12 \
        Correct "This demo is useful"        off \
        Fun        "This demo is nice"        off \
        Strong        "This demo is complex"        on 2>&1 >/dev/tty)
    AnsRadio=$($DIALOG --radiolist "I will:" 20 60 12 \
        " -1" "Downgrade this answer"        off \
        "  0" "Not do anything"                on \
        " +1" "Upgrade this anser"        off 2>&1 >/dev/tty)
    out="Your answers:\nLike: $AnsYesNo\nInput: $AnsInput\nSecret: $AnsPass"
    $DIALOG --msgbox "$out\nAttribs: $AnsCkLst\nNote: $AnsRadio" 20 60
  done

Еще пример? Посмотрите, как использовать whiptail для выбора USB-устройства и USB-съемного переключателя хранения: USBKeyChooser

5. Использование истории чтения

Пример:

#!/bin/bash

set -i
HISTFILE=~/.myscript.history
history -c
history -r

myread() {
    read -e -p '> ' $1
    history -s ${!1}
}
trap 'history -a;exit' 0 1 2 3 6

while myread line;do
    case ${line%% *} in
        exit )  break ;;
        *    )  echo "Doing something with '$line'" ;;
      esac
  done

Это создаст файл .myscript.history в вашем каталоге $HOME , чем вы могли бы использовать команды истории чтения, такие как Up , Down , Ctrl + r и другие.


Ты хочешь:

  • Встроенные команды Bash (например, переносные)
  • Проверка TTY
  • Ответ по умолчанию
  • Тайм-аут
  • Цветной вопрос

отрывок

do_xxxx=y                      # In batch mode => Default is Yes
[[ -t 0 ]] &&                  # If TTY => Prompt the question
read -n 1 -p $'\e[1;32m
Do xxxx? (Y/n)\e[0m ' do_xxxx  # Store the answer in $do_xxxx
if [[ $do_xxxx =~ ^(y|Y|)$ ]]  # Do if 'y' or 'Y' or empty
then
    xxxx
fi

Пояснения

  • [[ -t 0 ]] && read ... => Вызов команды read если TTY
  • read -n 1 => Ожидание одного символа
  • $'\e[1;32m ... \e[0m ' => Печать зеленым цветом
    (зеленый - это хорошо, потому что он читается как на белом, так и на черном фоне)
  • [[ $do_xxxx =~ ^(y|Y|)$ ]] => bash regex

Таймаут => Ответ по умолчанию - Нет

do_xxxx=y
[[ -t 0 ]] && {                   # Timeout 5 seconds (read -t 5)
read -t 5 -n 1 -p $'\e[1;32m
Do xxxx? (Y/n)\e[0m ' do_xxxx ||  # read 'fails' on timeout
do_xxxx=n ; }                     # Timeout => answer No
if [[ $do_xxxx =~ ^(y|Y|)$ ]]
then
    xxxx
fi

Бэш select для этой цели.

select result in Yes No Cancel
do
    echo $result
done

В ответ другим:

Вам не нужно указывать случай в BASH4, просто используйте «,,», чтобы сделать var в нижнем регистре. Также я сильно не люблю помещать код внутри блока чтения, получать результат и обрабатывать его вне блока чтения IMO. Также укажите «q» для выхода из IMO. И наконец, зачем «да» просто использовать -n1 и нажать y.

Пример: пользователь может нажать y / n, а также q, чтобы просто выйти.

ans=''
while true; do
    read -p "So is MikeQ the greatest or what (y/n/q) ?" -n1 ans
    case ${ans,,} in
        y|n|q) break;;
        *) echo "Answer y for yes / n for no  or q for quit.";;
    esac
done

echo -e "\nAnswer = $ans"

if [[ "${ans,,}" == "q" ]] ; then
        echo "OK Quitting, we will assume that he is"
        exit 0
fi

if [[ "${ans,,}" == "y" ]] ; then
        echo "MikeQ is the greatest!!"
else
        echo "No? MikeQ is not the greatest?"
fi

Вариант с несколькими вариантами:

ask () {                        # $1=question $2=options
    # set REPLY
    # options: x=..|y=..
    while $(true); do
        printf '%s [%s] ' "$1" "$2"
        stty cbreak
        REPLY=$(dd if=/dev/tty bs=1 count=1 2> /dev/null)
        stty -cbreak
        test "$REPLY" != "$(printf '\n')" && printf '\n'
        (
            IFS='|'
            for o in $2; do
                if [ "$REPLY" = "${o%%=*}" ]; then
                    printf '\n'
                    break
                fi
            done
        ) | grep ^ > /dev/null && return
    done
}

Пример:

$ ask 'continue?' 'y=yes|n=no|m=maybe'
continue? [y=yes|n=no|m=maybe] g
continue? [y=yes|n=no|m=maybe] k
continue? [y=yes|n=no|m=maybe] y
$

Он установит REPLY в y (внутри скрипта).


Вот что я собрал:

#!/bin/sh

promptyn () {
    while true; do
        read -p "$1 " yn
        case $yn in
            [Yy]* ) return 0;;
            [Nn]* ) return 1;;
            * ) echo "Please answer yes or no.";;
        esac
    done
}

if promptyn "is the sky blue?"; then
    echo "yes"
else
    echo "no"
fi

Я новичок, поэтому возьмите это с солью, но, похоже, это сработает.


Вы можете использовать встроенную команду read ; Используйте параметр -p чтобы запросить у пользователя вопрос.

Начиная с BASH4, теперь вы можете использовать -i чтобы предложить ответ, поэтому пользователю нужно только нажать return чтобы ввести его:

read -e -p "Enter the path to the file: " -i "/usr/local/etc/" FILEPATH
echo $FILEPATH

(Но не забудьте использовать параметр «readline» -e чтобы разрешить редактирование строк со стрелками)

Если вы хотите логику «да / нет», вы можете сделать что-то вроде этого:

read -e -p "
List the content of your home dir ? [Y/n] " YN

[[ $YN == "y" || $YN == "Y" || $YN == "" ]] && ls -la ~/

Используйте команду read :

echo Would you like to install? "(Y or N)"

read x

# now check if $x is "y"
if [ "$x" = "y" ]; then
    # do something here!
fi

а затем весь другой материал, который вам нужен


Один простой способ сделать это - xargs -p или gnu parallel --interactive .

Мне нравится поведение xargs немного лучше для этого, потому что он выполняет каждую команду сразу после приглашения, как и другие интерактивные команды unix, вместо того, чтобы собирать yesses для запуска в конце. (Вы можете Ctrl-C после того, как вы пройдете те, которые вам нужны.)

например,

echo *.xml | xargs -p -n 1 -J {} mv {} backup/

Чтобы получить приятный ncurses-like inputbox, используйте диалоговое окно команд следующим образом:

#!/bin/bash
if (dialog --title "Message" --yesno "Want to do something risky?" 6 25)
# message box will have the size 25x6 characters
then 
    echo "Let's do something risky"
    # do something risky
else 
    echo "Let's stay boring"
fi

Пакет диалогов устанавливается по умолчанию, по крайней мере, с SUSE Linux.


Это решение считывает один символ и вызывает функцию ответа «да».

read -p "Are you sure? (y/n) " -n 1
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
    do_something      
fi

Я использовал case пару раз в таком сценарии, используя аргумент case - это хороший способ сделать это. Цикл while, который инициализирует блок case , который использует логическое условие, может быть реализован для того, чтобы еще больше контролировать программу и выполнять многие другие требования. После того, как все условия будут выполнены, можно использовать break , который будет проходить контроль до основной части программы. Кроме того, для удовлетворения других условий, конечно, могут быть добавлены условные утверждения для сопровождения структур управления: case statement и возможный цикл while.

Пример использования оператора case для выполнения вашего запроса

#! /bin/sh 

# For potential users of BSD, or other systems who do not
# have a bash binary located in /bin the script will be directed to
# a bourne-shell, e.g. /bin/sh

# NOTE: It would seem best for handling user entry errors or
# exceptions, to put the decision required by the input 
# of the prompt in a case statement (case control structure), 

echo Would you like us to perform the option: "(Y|N)"

read inPut

case $inPut in
    # echoing a command encapsulated by 
    # backticks (``) executes the command
    "Y") echo `Do something crazy`
    ;;
    # depending on the scenario, execute the other option
    # or leave as default
    "N") echo `execute another option`
    ;;
esac

exit

Я предлагаю вам использовать диалог ...

Linux Apprentice: улучшите скрипты командной строки Bash с помощью диалога

Команда dialog позволяет использовать окна в сценариях оболочки, чтобы сделать их использование более интерактивным.

он прост и удобен в использовании, также есть версия gnome под названием gdialog, которая принимает точно такие же параметры, но показывает ее стиль GUI на X.


Самый простой и наиболее распространенный метод получения пользовательского ввода в командной строке - команда read . Лучшим способом проиллюстрировать его использование является простая демонстрация:

while true; do
    read -p "Do you wish to install this program?" yn
    case $yn in
        [Yy]* ) make install; break;;
        [Nn]* ) exit;;
        * ) echo "Please answer yes or no.";;
    esac
done

Другой метод, на который указывает Стивен Хувиг, - это команда select Баша. Вот тот же пример с использованием select :

echo "Do you wish to install this program?"
select yn in "Yes" "No"; do
    case $yn in
        Yes ) make install; break;;
        No ) exit;;
    esac
done

С помощью select вам не нужно санировать вход - он отображает доступные варианты, и вы вводите число, соответствующее вашему выбору. Он также автоматически зацикливается, поэтому нет необходимости в повторном цикле while true цикла, если они выдают неверный ввод.

Кроме того, пожалуйста, проверьте отличный ответ Ф. Хаури.


echo "Please enter some input: "
read input_variable
echo "You entered: $input_variable"

read -e -p "Enter your choice: " choice

Опция -e позволяет пользователю редактировать ввод с помощью клавиш со стрелками.

Если вы хотите использовать предложение в качестве входных данных:

read -e -i "yes" -p "Enter your choice: " choice

-i выводит наводящий ввод.


read -p "Are you alright? (y/n) " RESP
if [ "$RESP" = "y" ]; then
  echo "Glad to hear it"
else
  echo "You need more bash programming"
fi




scripting