Saya ingin menjeda input dalam skrip shell, dan meminta pengguna untuk memilih.
Pertanyaan standar Yes
,, No
atau Cancel
jenis.
Bagaimana cara melakukannya dalam bash prompt yang khas?
read
perintah untuk meminta
Saya ingin menjeda input dalam skrip shell, dan meminta pengguna untuk memilih.
Pertanyaan standar Yes
,, No
atau Cancel
jenis.
Bagaimana cara melakukannya dalam bash prompt yang khas?
read
perintah untuk meminta
Jawaban:
Metode paling sederhana dan paling banyak tersedia untuk mendapatkan input pengguna pada prompt shell adalah read
perintahnya. Cara terbaik untuk menggambarkan penggunaannya adalah demonstrasi sederhana:
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
Metode lain, ditunjukkan oleh Steven Huwig , adalah select
perintah Bash . Berikut adalah contoh yang sama menggunakan 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
Dengan select
Anda tidak perlu membersihkan input - ini akan menampilkan pilihan yang tersedia, dan Anda mengetik angka yang sesuai dengan pilihan Anda. Itu juga loop otomatis, jadi tidak perlu while true
loop untuk mencoba lagi jika mereka memberikan input yang tidak valid.
Juga, Léa Gris menunjukkan cara untuk membuat bahasa permintaan agnostik dalam jawabannya . Mengadaptasi contoh pertama saya untuk melayani berbagai bahasa dengan lebih baik mungkin terlihat seperti ini:
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
Jelas string komunikasi lainnya tetap tidak diterjemahkan di sini (Instal, Jawab) yang perlu ditangani dalam terjemahan yang lebih lengkap, tetapi bahkan terjemahan parsial akan membantu dalam banyak kasus.
Akhirnya, silakan periksa jawaban luar biasa dari F. Hauri .
exit
untuk break
menjaga dari penutupan tab ketika saya memilih 'tidak'.
break
di select
jika tidak ada loop?
Bergantung kepada
dan jika kamu mau
Anda bisa menggunakan read
perintah, diikuti oleh 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
(Terima kasih atas komentar Adam Katz : Mengganti tes di atas dengan yang lebih portabel dan menghindari satu garpu :)
Tetapi jika Anda tidak ingin pengguna harus menekan Return, Anda dapat menulis:
( Diedit: Seperti yang disarankan oleh @JonathanLeffler dengan benar, menyimpan konfigurasi stty bisa lebih baik daripada sekadar memaksa mereka untuk waras .)
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
Catatan: Ini diuji di bawahSH, pesta, ksh, berlari dan busybox!
Sama, tetapi menunggu secara eksplisit untuk yatau 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
Ada banyak alat yang dibangun menggunakan libncurses
, libgtk
, libqt
atau perpustakaan grafis lainnya. Misalnya, menggunakan whiptail
:
if whiptail --yesno "Is this a good question" 20 60 ;then
echo Yes
else
echo No
fi
Bergantung pada sistem Anda, Anda mungkin perlu mengganti whiptail
dengan alat serupa lainnya:
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
di mana 20
tinggi kotak dialog dalam jumlah garis dan 60
lebar kotak dialog. Semua alat ini memiliki sintaks yang hampir sama .
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
Saya lebih suka menggunakan case
sehingga saya bahkan bisa menguji yes | ja | si | oui
jika diperlukan ...
Di bawah bash, kita dapat menentukan panjang input yang dimaksudkan untuk read
perintah:
read -n 1 -p "Is this a good question (y/n)? " answer
Di bawah bash, read
perintah menerima parameter batas waktu , yang bisa berguna.
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
Kotak dialog yang lebih canggih, di luar yes - no
tujuan sederhana :
dialog --menu "Is this a good question" 20 60 12 y Yes n No m Maybe
Bilah kemajuan:
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
)
Demo kecil:
#!/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
Lebih banyak sampel? Lihat Menggunakan whiptail untuk memilih perangkat USB dan pemilih penyimpanan yang dapat dilepas USB: USBKeyChooser
Contoh:
#!/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
Ini akan membuat file .myscript.history
di Anda $HOME
direktori, daripada Anda bisa menggunakan perintah sejarah readline ini, seperti Up, Down, Ctrl+ rdan lain-lain.
stty
menyediakan -g
pilihan untuk digunakan: old_stty=$(stty -g); stty raw -echo; …; stty "$old_stty"
. Ini mengembalikan pengaturan persis seperti yang ditemukan, yang mungkin atau mungkin tidak sama dengan stty -sane
.
case
untuk POSIX dan juga bash (gunakan kondisi wildcard daripada substring bash:) case $answer in; [Yy]* ) echo Yes ;;
, tapi saya lebih suka menggunakan pernyataan kondisional, [ "$answer" != "${answer#[Yy]}" ]
lebih memilih daripada echo "$answer" | grep -iq ^y
. Ini lebih portabel (beberapa greps non-GNU tidak menerapkan -q
dengan benar) dan tidak memiliki panggilan sistem. ${answer#[Yy]}
menggunakan ekspansi parameter untuk menghapus Y
atau y
dari awal $answer
, menyebabkan ketidaksetaraan saat ada. Ini berfungsi di semua shell POSIX (tanda hubung, ksh, bash, zsh, busybox, dll).
echo "Please enter some input: "
read input_variable
echo "You entered: $input_variable"
Anda dapat menggunakan perintah baca bawaan; Menggunakan-p
opsi untuk meminta pengguna dengan pertanyaan.
Sejak BASH4, sekarang Anda dapat menggunakan -i
untuk menyarankan jawaban:
read -e -p "Enter the path to the file: " -i "/usr/local/etc/" FILEPATH
echo $FILEPATH
(Tapi ingat untuk menggunakan opsi "readline" -e
untuk memungkinkan pengeditan baris dengan tombol panah)
Jika Anda menginginkan logika "ya / tidak", Anda dapat melakukan sesuatu seperti ini:
read -e -p "
List the content of your home dir ? [Y/n] " YN
[[ $YN == "y" || $YN == "Y" || $YN == "" ]] && ls -la ~/
FILEPATH
adalah nama variabel yang Anda pilih, dan diatur dengan jawaban ke prompt perintah. Jadi jika Anda menjalankannya vlc "$FILEPATH"
, misalnya, vlc
akan membuka file itu.
-e
contoh kedua (sederhana ya / tidak)?
-e -p
bukan -ep
?
-e
tanda / opsi, Anda mungkin (tergantung pada implementasinya) tidak dapat mengetik "y", dan kemudian berubah pikiran dan menggantinya dengan "n" (atau apa pun dalam hal ini); Ketika mendokumentasikan perintah, daftar opsi secara terpisah lebih baik untuk keterbacaan / kejelasan, antara alasan lainnya.
Bash telah memilih untuk tujuan ini.
select result in Yes No Cancel
do
echo $result
done
exit
dalam :)
Ctrl-D
Tapi tentu saja, kode nyata yang menggunakannya akan membutuhkan istirahat atau jalan keluar di tubuh.)
exit
akan keluar dari script bersama-sama, break
hanya akan keluar dari loop Anda (jika Anda berada di while
atau case
loop)
Inilah sesuatu yang saya kumpulkan:
#!/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
Saya seorang pemula, jadi ambil ini dengan sebutir garam, tetapi sepertinya berhasil.
case $yn in
ke case ${yn:-$2} in
maka Anda dapat menggunakan argumen kedua sebagai nilai default, Y atau N.
case $yn
ke case "${yn:-Y}"
memiliki ya sebagai default
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 ...
=> Panggil perintah read
jika TTYread -n 1
=> Tunggu satu karakter$'\e[1;32m ... \e[0m '
=> Mencetak hijau [[ $do_xxxx =~ ^(y|Y|)$ ]]
=> bash 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
Cara termudah untuk mencapai ini dengan paling sedikit garis adalah sebagai berikut:
read -p "<Your Friendly Message here> : y/n/cancel" CONDITION;
if [ "$CONDITION" == "y" ]; then
# do something here!
fi
Ini if
hanyalah sebuah contoh: terserah Anda bagaimana menangani variabel ini.
Gunakan read
perintah:
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
dan kemudian semua hal lain yang Anda butuhkan
Solusi ini membaca satu karakter dan memanggil fungsi pada respons ya.
read -p "Are you sure? (y/n) " -n 1
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
do_something
fi
echo
untuk melihat sendiri.
Untuk mendapatkan inputbox ncurses-like yang bagus gunakan dialog perintah seperti ini:
#!/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
Paket dialog diinstal secara default setidaknya dengan SUSE Linux. Seperti:
read -e -p "Enter your choice: " choice
Itu -e
pilihan memungkinkan pengguna untuk mengedit masukan menggunakan tombol panah.
Jika Anda ingin menggunakan saran sebagai masukan:
read -e -i "yes" -p "Enter your choice: " choice
-i
opsi mencetak input sugestif.
-e
-i
jangan bekerja di sh (Bourne shell), tetapi pertanyaannya ditandai bash khusus ..
Anda dapat menggunakan default REPLY
pada a read
, konversikan ke huruf kecil dan bandingkan dengan serangkaian variabel dengan ekspresi.
Skrip juga mendukung 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
Dimungkinkan untuk menangani "Ya / Tidak pilihan" sadar-lokal di shell POSIX; dengan menggunakan entri dari LC_MESSAGES
kategori lokal, penyihir menyediakan pola RegEx yang sudah jadi untuk mencocokkan input, dan string untuk dilokalisasi Ya Tidak.
#!/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: Seperti yang disebutkan oleh @Urhixidur dalam komentarnya :
Sayangnya, POSIX hanya menentukan dua yang pertama (yesexpr dan noexpr). Di Ubuntu 16, yesstr dan nostr kosong.
Lihat: https://www.ee.ryerson.ca/~courses/ele709/susv4/xrat/V4_xbd_chap07.html#tag_21_07_03_06
LC_MESSAGES
Kata kunci
yesstr
dannostr
lokal serta itemYESSTR
danNOSTR
langinfo sebelumnya digunakan untuk mencocokkan respons afirmatif dan negatif pengguna. Dalam POSIX.1-2008, yangyesexpr
,noexpr
,YESEXPR
, danNOEXPR
diperpanjang ekspresi reguler telah menggantikan mereka. Aplikasi harus menggunakan fasilitas perpesanan berbasis lokal umum untuk mengeluarkan pesan prompt yang menyertakan sampel respons yang diinginkan.
Atau menggunakan lokal dengan cara 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
Jawabannya cocok dengan menggunakan regexps yang disediakan lingkungan lokal.
Untuk menerjemahkan pesan yang tersisa, gunakan bash --dump-po-strings scriptname
untuk mengeluarkan string po untuk pelokalan:
#: 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
dan noexpr
dalam lingkungan shell, adalah menggunakannya dalam pencocokan RegEx spesifik Bashif [[ "$yn" =~ $yesexpr ]]; then echo $"Answered yes"; else echo $"Answered no"; fi
Inilah pendekatan yang lebih panjang, tetapi dapat digunakan kembali dan modular:
0
= ya dan 1
= tidakzsh
dan bash
.Perhatikan bahwa N
huruf kapital. Sini masuk ditekan, menerima default:
$ confirm "Show dangerous command" && echo "rm *"
Show dangerous command [y/N]?
Perhatikan juga, [y/N]?
itu ditambahkan secara otomatis. Default "tidak" diterima, jadi tidak ada yang digaungkan.
Konfirmasikan kembali hingga respons yang valid diberikan:
$ confirm "Show dangerous command" && echo "rm *"
Show dangerous command [y/N]? X
Show dangerous command [y/N]? y
rm *
Perhatikan bahwa Y
huruf kapital:
$ confirm_yes "Show dangerous command" && echo "rm *"
Show dangerous command [Y/n]?
rm *
Di atas, saya hanya menekan enter, jadi perintahnya berlari.
y
ataun
$ 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
Di sini, 1
atau false dikembalikan. Perhatikan bahwa dengan fungsi level yang lebih rendah ini Anda harus menyediakan [y/n]?
prompt Anda sendiri .
# 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]?
danShow dangerous command [Y/n]? [y/n]?
Maaf karena memposting pada posting lama. Beberapa minggu yang lalu saya menghadapi masalah yang sama, dalam kasus saya, saya membutuhkan solusi yang juga berfungsi dalam skrip pemasang online, misalnya:curl -Ss https://raw.github.com/_____/installer.sh | bash
Menggunakan read yesno < /dev/tty
berfungsi dengan baik untuk saya:
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
Semoga ini bisa membantu seseorang.
tty
input seperti yang Anda lakukan akan melakukannya juga untuk Anda, dan juga mendapatkan perulangan pada input yang buruk (bayangkan beberapa karakter dalam buffer; metode Anda akan memaksa pengguna untuk selalu memilih tidak).
Saya perhatikan bahwa tidak ada yang memposting jawaban yang menunjukkan menu gema multi-line untuk input pengguna yang begitu sederhana jadi inilah yang saya lakukan:
#!/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
Metode ini diposting dengan harapan bahwa seseorang dapat menemukannya berguna dan menghemat waktu.
Versi pilihan ganda:
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
}
Contoh:
$ 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
$
Ini akan diatur REPLY
ke y
(di dalam skrip).
Saya sarankan Anda menggunakan dialog ...
Linux Apprentice: Tingkatkan Skrip Bash Shell Menggunakan Dialog
Perintah dialog memungkinkan penggunaan kotak jendela dalam skrip shell untuk membuat penggunaannya lebih interaktif.
itu sederhana dan mudah digunakan, ada juga versi gnome yang disebut gdialog yang mengambil parameter yang sama persis, tetapi menunjukkannya gaya GUI di X.
Terinspirasi oleh jawaban @Mark dan @Myrddin saya membuat fungsi ini untuk prompt universal
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
}
gunakan seperti ini:
unipromtp "Select an option: (a)-Do one (x)->Do two (f)->Do three : " "a x f" selection
echo "$selection"
akan lebih umum:
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
}
Salah satu cara sederhana untuk melakukan ini adalah dengan xargs -p
atau gnu parallel --interactive
.
Saya suka perilaku xargs sedikit lebih baik untuk ini karena ia mengeksekusi setiap perintah segera setelah prompt seperti perintah unix interaktif lainnya, daripada mengumpulkan yesses untuk dijalankan di akhir. (Anda dapat Ctrl-C setelah melewati yang Anda inginkan.)
misalnya,
echo *.xml | xargs -p -n 1 -J {} mv {} backup/
xargs --interactive
terbatas pada ya atau tidak. Selama itu saja yang Anda butuhkan, itu sudah cukup, tetapi pertanyaan awal saya memberi contoh dengan tiga kemungkinan hasil. Saya sangat suka itu bisa di-streamable; banyak skenario umum akan mendapat manfaat dari kemampuannya untuk disalurkan.
Sebagai teman dari perintah satu baris saya menggunakan yang berikut:
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=;
Bentuk panjang tertulis, kerjanya seperti ini:
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=;
Saya telah menggunakan case
pernyataan itu beberapa kali dalam skenario seperti itu, menggunakan statment kasus adalah cara yang baik untuk menyelesaikannya. Sebuah while
loop, yang meng-ecapsulate case
blok, yang memanfaatkan kondisi boolean dapat diimplementasikan untuk memegang kendali lebih besar terhadap program, dan memenuhi banyak persyaratan lainnya. Setelah semua persyaratan telah terpenuhi, break
dapat digunakan yang akan melewati kontrol kembali ke bagian utama dari program. Juga, untuk memenuhi kondisi lain, tentu saja pernyataan kondisional dapat ditambahkan untuk menyertai struktur kontrol: case
pernyataan dan kemungkinan while
perulangan.
Contoh menggunakan case
pernyataan untuk memenuhi permintaan Anda
#! /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
Menanggapi orang lain:
Anda tidak perlu menentukan kasus di BASH4 cukup gunakan ',,' untuk membuat huruf kecil var. Saya juga sangat tidak suka menempatkan kode di dalam blok baca, dapatkan hasilnya dan mengatasinya di luar blok baca IMO. Juga sertakan 'q' untuk keluar dari IMO. Terakhir, mengapa mengetik 'ya' cukup gunakan -n1 dan tekan tombol y.
Contoh: pengguna dapat menekan y / n dan juga q untuk berhenti saja.
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
Seringkali dalam skenario seperti itu, Anda harus terus menjalankan skrip hingga pengguna terus memasukkan "ya" dan hanya perlu berhenti ketika pengguna memasukkan "tidak". Cuplikan di bawah ini akan membantu Anda mencapai ini!
#!/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]
opsi, yang dikapitalisasi adalah default, yaitu[Yn]
default ke "ya", dan[yN]
default ke "tidak". Lihat ux.stackexchange.com/a/40445/43532