Я хочу призупинити введення в скрипті оболонки та запропонувати користувачеві вибрати.
Стандартний Yes
, No
або Cancel
типу питання.
Як мені це зробити в типовому підказі на башти?
read
команду для
Я хочу призупинити введення в скрипті оболонки та запропонувати користувачеві вибрати.
Стандартний Yes
, No
або Cancel
типу питання.
Як мені це зробити в типовому підказі на башти?
read
команду для
Відповіді:
Найпростіший і найпоширеніший спосіб отримати введення користувача в командному рядку оболонки - це 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
Інший метод, вказав на Стівена Huwig , є в Bash 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
циклічно циклічний , тому петлі не потрібно повторювати, якщо вони дають недійсні дані.
Також Леа Гріс продемонструвала спосіб зробити мову запиту агностиком у своїй відповіді . Адаптація мого першого прикладу для кращого обслуговування декількох мов може виглядати так:
set -- $(locale LC_MESSAGES)
yesptrn="$1"; noptrn="$2"; yesword="$3"; noword="$4"
while true; do
read -p "Install (${yesword} / ${noword})? " yn
case $yn in
${yesptrn##^} ) make install; break;;
${noptrn##^} ) exit;;
* ) echo "Answer ${yesword} / ${noword}.";;
esac
done
Очевидно, що інші рядки комунікації залишаються неперекладеними (Встановити, відповісти), що потрібно було б вирішити у більш повному перекладі, але навіть частковий переклад був би корисним у багатьох випадках.
Нарешті, будь ласка , перевірте відмінний відповідь на Ф. Хаурі .
exit
щоб break
не закривати вкладку, коли вибрав "ні".
break
в select
разі немає циклу?
В залежності від
і якщо хочете
Ви можете використовувати 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
(Завдяки коментарю Адама Каца : замінив тест вище на те, що є більш портативним і уникає однієї вилки :)
Але якщо ви не хочете, щоб користувач мав ударяти 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
Примітка. Це було випробувано вш, баш, кш, тире і busbox!
Те саме, але чекаючи прямо 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 ...
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
необхідність ...
Під 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
Приклад:
#!/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
каталозі, ніж ви могли б використовувати команди історії Readline, як і Up, Down, Ctrl+ rта інші.
stty
забезпечує -g
можливість для використання: old_stty=$(stty -g); stty raw -echo; …; stty "$old_stty"
. Це відновлює налаштування саме так, як вони були знайдені, які можуть бути або не бути такими, як stty -sane
.
case
для POSIX, так і для bash (використовуйте умовні підстановки, а не bash-підрядку:) case $answer in; [Yy]* ) echo Yes ;;
, але я вважаю за краще використовувати умовне твердження замість цього, віддаючи перевагу [ "$answer" != "${answer#[Yy]}" ]
над вашим echo "$answer" | grep -iq ^y
. Він більш портативний (деякі не-GNU-грейпи не реалізуються -q
правильно) і не має системного виклику. ${answer#[Yy]}
використовує розширення параметрів для вилучення Y
або y
з початку $answer
, викликаючи нерівність, коли будь-який присутній. Це працює в будь-якій оболонці POSIX (тире, ksh, bash, zsh, busybox тощо).
echo "Please enter some input: "
read input_variable
echo "You entered: $input_variable"
Ви можете використовувати вбудовану команду читання ; Використовуйте -p
опцію, щоб підказати користувачеві питання.
З BASH4 тепер ви можете -i
запропонувати відповідь:
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 ~/
FILEPATH
це ім'я змінної, яку ви вибрали, і задається відповіддю на командний рядок. Отже, якби ви тоді запустили vlc "$FILEPATH"
, наприклад, vlc
відкрили б цей файл.
-e
у другому прикладі (простий так / ні)?
-e -p
замість -ep
?
-e
прапора / опції, ви можете (залежно від реалізації) не зможете набрати "y", а потім змінити свою думку і замінити його на "n" (або що-небудь інше з цього питання); Під час документування команди, перелік параметрів окремо є кращим для читабельності / чіткості, серед інших причин.
Для цього Bash вибрав .
select result in Yes No Cancel
do
echo $result
done
exit
всередину :)
Ctrl-D
Але звичайно, для реального коду, який використовує його, знадобиться перерва або вихід у тілі.)
exit
вийдуть із сценарію всі разом, break
вийдуть лише з циклу, в якому ви перебуваєте (якщо ви знаходитесь у циклі) while
абоcase
Ось що я зібрав:
#!/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
Я початківець, тому прийміть це із зерном солі, але, здається, це працює.
case $yn in
на case ${yn:-$2} in
то, ви можете використовувати другий аргумент як значення за замовчуванням, Y або N.
case $yn
щоб case "${yn:-Y}"
мати за замовчуванням так
inquire () {
echo -n "$1 [y/n]? "
read answer
finish="-1"
while [ "$finish" = '-1' ]
do
finish="1"
if [ "$answer" = '' ];
then
answer=""
else
case $answer in
y | Y | yes | YES ) answer="y";;
n | N | no | NO ) answer="n";;
*) finish="-1";
echo -n 'Invalid response -- please reenter:';
read answer;;
esac
fi
done
}
... other stuff
inquire "Install now?"
...
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
якщо TTYread -n 1
=> Зачекайте одного символу$'\e[1;32m ... \e[0m '
=> Друк зеленим кольором [[ $do_xxxx =~ ^(y|Y|)$ ]]
=> bashe regexdo_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
Найпростіший спосіб досягти цього з найменшою кількістю рядків:
read -p "<Your Friendly Message here> : y/n/cancel" CONDITION;
if [ "$CONDITION" == "y" ]; then
# do something here!
fi
Це if
лише приклад: від вас залежить, як поводитися з цією змінною.
Використовуйте 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
а потім усі інші речі, які вам потрібні
Це рішення зчитує один символ та викликає функцію у відповідь "так".
read -p "Are you sure? (y/n) " -n 1
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
do_something
fi
echo
щоб побачити самі.
Щоб отримати гарне вхідне поле, схоже на ncurses, скористайтеся таким діалоговим вікном команд :
#!/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 -e -p "Enter your choice: " choice
Ця -e
опція дозволяє користувачеві редагувати дані за допомогою клавіш зі стрілками.
Якщо ви хочете використовувати пропозицію як вхід:
read -e -i "yes" -p "Enter your choice: " choice
-i
опція друкує сугестивний ввід.
-e
-i
не працюйте в ш (
Ви можете використовувати за замовчуванням REPLY
на a read
, перетворити в малі та порівняти з набором змінних з виразом.
Сценарій також підтримує ja
/ si
/oui
read -rp "Do you want a demo? [y/n/c] "
[[ ${REPLY,,} =~ ^(c|cancel)$ ]] && { echo "Selected Cancel"; exit 1; }
if [[ ${REPLY,,} =~ ^(y|yes|j|ja|s|si|o|oui)$ ]]; then
echo "Positive"
fi
Є можливість обробляти "Так / Ні вибір", відомий локалі, в оболонці POSIX; використовуючи записи LC_MESSAGES
категорії локалів, відьма забезпечує готові шаблони RegEx для відповідності вводу та рядки для локалізованого Так. Ні.
#!/usr/bin/env sh
# Getting LC_MESSAGES values into variables
# shellcheck disable=SC2046 # Intended IFS splitting
IFS='
' set -- $(locale LC_MESSAGES)
yesexpr="$1"
noexpr="$2"
yesstr="$3"
nostr="$4"
messages_codeset="$5" # unused here, but kept as documentation
# Display Yes / No ? prompt into locale
echo "$yesstr / $nostr ?"
# Read answer
read -r yn
# Test answer
case "$yn" in
# match only work with the character class from the expression
${yesexpr##^}) echo "answer $yesstr" ;;
${noexpr##^}) echo "answer $nostr" ;;
esac
EDIT: Як @Urhixidur згадував у своєму коментарі :
На жаль, POSIX вказує лише перші два (yesexpr і noexpr). На Ubuntu 16, yesstr і nostr порожні.
Дивіться: https://www.ee.ryerson.ca/~courses/ele709/susv4/xrat/V4_xbd_chap07.html#tag_21_07_03_06
LC_MESSAGES
yesstr
Іnostr
локал ключові слова іYESSTR
таNOSTR
langinfo елементів раніше були використані для призначеного для користувача матчу позитивних і негативних відповідей. У POSIX.1-2008, тимyesexpr
,noexpr
,YESEXPR
, іNOEXPR
розширені регулярні вирази замінили їх. Програми повинні використовувати загальні засоби обміну повідомленнями на основі локальної локації, щоб видавати спонукальні повідомлення, які містять вибірки бажаних відповідей.
Крім того, використовуючи локалі Bash:
#!/usr/bin/env bash
IFS=$'\n' read -r -d '' yesexpr noexpr _ < <(locale LC_MESSAGES)
printf -v yes_or_no_regex "(%s)|(%s)" "$yesexpr" "$noexpr"
printf -v prompt $"Please answer Yes (%s) or No (%s): " "$yesexpr" "$noexpr"
declare -- answer=;
until [[ "$answer" =~ $yes_or_no_regex ]]; do
read -rp "$prompt" answer
done
if [[ -n "${BASH_REMATCH[1]}" ]]; then
echo $"You answered: Yes"
else
echo $"No, was your answer."
fi
Відповідь узгоджується за допомогою наданих зворотних зон локального середовища.
Для перекладу решти повідомлень використовуйте bash --dump-po-strings scriptname
для виведення po рядків для локалізації:
#: scriptname:8
msgid "Please answer Yes (%s) or No (%s): "
msgstr ""
#: scriptname:17
msgid "You answered: Yes"
msgstr ""
#: scriptname:19
msgid "No, was your answer."
msgstr ""
yesexpr
і noexpr
в середовищі оболонки, є використання їх у відповідність конкретних RegEx Bashif [[ "$yn" =~ $yesexpr ]]; then echo $"Answered yes"; else echo $"Answered no"; fi
Ось більш тривалий, але багаторазовий і модульний підхід:
0
= так і 1
= ніzsh
і для bash
.Зауважте, що N
величина з великим капіталом. Тут натискається клавіша Enter, приймаючи за замовчуванням:
$ confirm "Show dangerous command" && echo "rm *"
Show dangerous command [y/N]?
Також зауважте, що [y/N]?
було додано автоматично. За замовчуванням "ні" приймається, тому нічого не повторюється.
Повторне запрошення, поки не буде надана дійсна відповідь:
$ confirm "Show dangerous command" && echo "rm *"
Show dangerous command [y/N]? X
Show dangerous command [y/N]? y
rm *
Зауважте, що з Y
великої літери:
$ confirm_yes "Show dangerous command" && echo "rm *"
Show dangerous command [Y/n]?
rm *
Вище я просто натиснув клавішу enter, тому команда бігла.
y
абоn
$ get_yes_keypress "Here you cannot press enter. Do you like this [y/n]? "
Here you cannot press enter. Do you like this [y/n]? k
Here you cannot press enter. Do you like this [y/n]?
Here you cannot press enter. Do you like this [y/n]? n
$ echo $?
1
Тут 1
або повернуто помилкове. Зауважте, що за допомогою цієї функції нижчого рівня вам потрібно буде забезпечити своє[y/n]?
запит.
# Read a single char from /dev/tty, prompting with "$*"
# Note: pressing enter will return a null string. Perhaps a version terminated with X and then remove it in caller?
# See https://unix.stackexchange.com/a/367880/143394 for dealing with multi-byte, etc.
function get_keypress {
local REPLY IFS=
>/dev/tty printf '%s' "$*"
[[ $ZSH_VERSION ]] && read -rk1 # Use -u0 to read from STDIN
# See https://unix.stackexchange.com/q/383197/143394 regarding '\n' -> ''
[[ $BASH_VERSION ]] && </dev/tty read -rn1
printf '%s' "$REPLY"
}
# Get a y/n from the user, return yes=0, no=1 enter=$2
# Prompt using $1.
# If set, return $2 on pressing enter, useful for cancel or defualting
function get_yes_keypress {
local prompt="${1:-Are you sure [y/n]? }"
local enter_return=$2
local REPLY
# [[ ! $prompt ]] && prompt="[y/n]? "
while REPLY=$(get_keypress "$prompt"); do
[[ $REPLY ]] && printf '\n' # $REPLY blank if user presses enter
case "$REPLY" in
Y|y) return 0;;
N|n) return 1;;
'') [[ $enter_return ]] && return "$enter_return"
esac
done
}
# Credit: http://unix.stackexchange.com/a/14444/143394
# Prompt to confirm, defaulting to NO on <enter>
# Usage: confirm "Dangerous. Are you sure?" && rm *
function confirm {
local prompt="${*:-Are you sure} [y/N]? "
get_yes_keypress "$prompt" 1
}
# Prompt to confirm, defaulting to YES on <enter>
function confirm_yes {
local prompt="${*:-Are you sure} [Y/n]? "
get_yes_keypress "$prompt" 0
}
Show dangerous command [y/N]? [y/n]?
іShow dangerous command [Y/n]? [y/n]?
Вибачте за публікацію на такому старому дописі. Деякі тижні тому я зіткнувся з подібною проблемою, і в моєму випадку мені було потрібно рішення, яке також працювало в сценарії онлайн-інсталятора, наприклад:curl -Ss https://raw.github.com/_____/installer.sh | bash
Використання read yesno < /dev/tty
добре працює для мене:
echo -n "These files will be uploaded. Is this ok? (y/n) "
read yesno < /dev/tty
if [ "x$yesno" = "xy" ];then
# Yes
else
# No
fi
Сподіваюся, що це комусь допоможе.
tty
введення так, як ви це зробили, як і для вас, а також зациклився на неправильному введенні (уявіть кілька символів у буфері; ваш метод змусить користувача завжди вибирати "ні").
Я помітив, що ніхто не опублікував відповідь, у якій відображалось багаторядкове ехо-меню для такого простого введення користувача, тому ось я іду на це:
#!/bin/bash
function ask_user() {
echo -e "
#~~~~~~~~~~~~#
| 1.) Yes |
| 2.) No |
| 3.) Quit |
#~~~~~~~~~~~~#\n"
read -e -p "Select 1: " choice
if [ "$choice" == "1" ]; then
do_something
elif [ "$choice" == "2" ]; then
do_something_else
elif [ "$choice" == "3" ]; then
clear && exit 0
else
echo "Please select 1, 2, or 3." && sleep 3
clear && ask_user
fi
}
ask_user
Цей метод був розміщений у надії, що хтось може вважати його корисним та економією часу.
Версія з декількома варіантами:
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
(всередині сценарію).
Я пропоную вам скористатися діалоговим вікном ...
Учень Linux: вдосконалення сценаріїв Bash Shell за допомогою діалогового вікна
Команда діалогу дозволяє використовувати вікна в скриптах оболонок, щоб зробити їх використання більш інтерактивним.
це простий і простий у використанні, також є версія gnome під назвою gdialog, яка приймає точно такі ж параметри, але показує її стиль GUI на X.
Натхненний відповідями @Mark та @Myrddin, я створив цю функцію для універсального підказу
uniprompt(){
while true; do
echo -e "$1\c"
read opt
array=($2)
case "${array[@]}" in *"$opt"*) eval "$3=$opt";return 0;; esac
echo -e "$opt is not a correct value\n"
done
}
використовуйте його так:
unipromtp "Select an option: (a)-Do one (x)->Do two (f)->Do three : " "a x f" selection
echo "$selection"
більш загальним було б:
function menu(){
title="Question time"
prompt="Select:"
options=("Yes" "No" "Maybe")
echo "$title"
PS3="$prompt"
select opt in "${options[@]}" "Quit/Cancel"; do
case "$REPLY" in
1 ) echo "You picked $opt which is option $REPLY";;
2 ) echo "You picked $opt which is option $REPLY";;
3 ) echo "You picked $opt which is option $REPLY";;
$(( ${#options[@]}+1 )) ) clear; echo "Goodbye!"; exit;;
*) echo "Invalid option. Try another one.";continue;;
esac
done
return
}
Один простий спосіб це зробити з xargs -p
або gnuparallel --interactive
.
Мені подобається, що поведінка xargs трохи краща для цього, оскільки вона виконує кожну команду одразу після підказки, як і інші інтерактивні команди Unix, а не збираючи даси для запуску в кінці. (Ви можете Ctrl-C після того, як пройдете ті, що хотіли.)
наприклад,
echo *.xml | xargs -p -n 1 -J {} mv {} backup/
xargs --interactive
обмежується так чи ні. Поки цього всього, що вам потрібно, може бути достатньо, але моє оригінальне запитання дало приклад з трьома можливими результатами. Мені дуже подобається, що воно є потоковим; багато загальних сценаріїв виграють від його здатності до трубопроводу.
Я як друг однорядкової команди використовував наступне:
while [ -z $prompt ]; do read -p "Continue (y/n)?" choice;case "$choice" in y|Y ) prompt=true; break;; n|N ) exit 0;; esac; done; prompt=;
Написаний longform, він працює так:
while [ -z $prompt ];
do read -p "Continue (y/n)?" choice;
case "$choice" in
y|Y ) prompt=true; break;;
n|N ) exit 0;;
esac;
done;
prompt=;
Я case
кілька разів використовував цю заяву в такому сценарії, використання регламенту справи є хорошим способом вирішити це. while
Петля, що ecapsulates в case
блоці, який використовує логічне умова може бути реалізована для того , щоб провести ще більший контроль над програмою, і виконати безліч інших вимог. Після того, як всі умови будуть виконані, break
може бути використаний талон, який поверне контроль до основної частини програми. Крім того, для задоволення інших умов, звичайно, можна додавати умовні заяви, які супроводжують структури управління: case
заява та можливі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
#!/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
yn() {
if [[ 'y' == `read -s -n 1 -p "[y/n]: " Y; echo $Y` ]];
then eval $1;
else eval $2;
fi }
yn 'echo yes' 'echo no'
yn 'echo absent no function works too!'
yn(){ read -s -n 1 -p '[y/n]'; test "$REPLY" = "y" ; } yn && echo success || echo failure
У відповідь на інших:
Вам не потрібно вказувати регістр в BASH4, просто скористайтеся символом ",," для створення рядкового рядка. Також я сильно не люблю вводити код всередину блоку читання, отримувати результат і мати справу з ним поза блоком читання 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
Більшість випадків у таких сценаріях вам потрібно продовжувати виконувати сценарій, поки користувач не вводить "так" і зупинятись потрібно лише тоді, коли користувач вводить "ні". Знизуваний фрагмент допоможе вам досягти цього!
#!/bin/bash
input="yes"
while [ "$input" == "yes" ]
do
echo "execute script functionality here..!!"
echo "Do you want to continue (yes/no)?"
read input
done
[yn]
параметр, той, який використовується з великої літери, є типовим, тобто[Yn]
за замовчуванням "так", а[yN]
за замовчуванням - "ні". Дивіться ux.stackexchange.com/a/40445/43532