Bagaimana saya meminta input Ya / Tidak / Batalkan dalam skrip shell Linux?
1444
Saya ingin menjeda input dalam skrip shell, dan meminta pengguna untuk memilih.
Pertanyaan standar Yes,, Noatau Canceljenis.
Bagaimana cara melakukannya dalam bash prompt yang khas?
Sama seperti catatan: konvensi untuk prompt adalah sedemikian rupa sehingga jika Anda menyajikan [yn]opsi, yang dikapitalisasi adalah default, yaitu [Yn]default ke "ya", dan [yN]default ke "tidak". Lihat ux.stackexchange.com/a/40445/43532
Tyzoid
Siapa pun yang datang ke sini dari ZSH, lihat jawaban ini untuk cara menggunakan readperintah untuk meminta
smac89
Jawaban:
1619
Metode paling sederhana dan paling banyak tersedia untuk mendapatkan input pengguna pada prompt shell adalah readperintahnya. 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.";;esacdone
Metode lain, ditunjukkan oleh Steven Huwig , adalah selectperintah Bash . Berikut adalah contoh yang sama menggunakan select:
echo "Do you wish to install this program?"
select yn in"Yes""No";docase $yn inYes) make install;break;;No) exit;;esacdone
Dengan selectAnda 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 trueloop 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}.";;esacdone
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.
Menggunakan Bash di OS X Leopard, aku berubah exituntuk breakmenjaga dari penutupan tab ketika saya memilih 'tidak'.
Trey Piepmeier
1
Bagaimana cara kerjanya dengan opsi yang lebih lama dari Ya atau Tidak? Dalam klausa kasus, apakah Anda menulis sesuatu seperti: Instal program dan jangan lakukan apa-apa setelah itu) melakukan instal; istirahat;
Shawn
1
@Shawn Menggunakan read Anda dapat, tentu saja, menggunakan pola glob atau regex yang didukung oleh pernyataan switch bash shell. Itu hanya cocok dengan teks yang diketik ke pola Anda sampai menemukan kecocokan. Menggunakan pilih , daftar pilihan diberikan kepada perintah dan itu menampilkannya kepada pengguna. Anda dapat memiliki item dalam daftar selama atau sesingkat yang Anda suka. Saya merekomendasikan memeriksa halaman manual mereka untuk informasi penggunaan yang komprehensif.
Myrddin Emrys
3
mengapa ada breakdi selectjika tidak ada loop?
Jayen
1
@akostadinov Saya benar-benar harus membaca riwayat edit saya lebih lanjut. Anda benar, saya salah, dan saya memperkenalkan bug mengikuti saran Jayan, hah. Bug itu kemudian diperbaiki, tetapi pengeditannya begitu jauh sehingga saya bahkan tidak ingat mengubahnya.
Myrddin Emrys
527
Setidaknya lima jawaban untuk satu pertanyaan umum.
Bergantung kepada
posix compliant: dapat bekerja pada sistem yang buruk dengan generik kulit lingkungan
(Terima kasih atas komentar Adam Katz : Mengganti tes di atas dengan yang lebih portabel dan menghindari satu garpu :)
POSIX, tetapi fitur kunci tunggal
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 sttyif echo "$answer"| grep -iq "^y";then
echo Yeselse
echo Nofi
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 Yeselse
echo Nofi
Menggunakan alat khusus
Ada banyak alat yang dibangun menggunakan libncurses, libgtk, libqtatau perpustakaan grafis lainnya. Misalnya, menggunakan whiptail:
if whiptail --yesno "Is this a good question"2060;then
echo Yeselse
echo Nofi
Bergantung pada sistem Anda, Anda mungkin perlu mengganti whiptaildengan alat serupa lainnya:
dialog --yesno "Is this a good question"2060&& echo Yes
gdialog --yesno "Is this a good question"2060&& echo Yes
kdialog --yesno "Is this a good question"2060&& echo Yes
di mana 20tinggi kotak dialog dalam jumlah garis dan 60lebar kotak dialog. Semua alat ini memiliki sintaks yang hampir sama .
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 casesehingga saya bahkan bisa menguji yes | ja | si | ouijika diperlukan ...
sejalan dengan fitur kunci tunggal
Di bawah bash, kita dapat menentukan panjang input yang dimaksudkan untuk readperintah:
read -n 1-p "Is this a good question (y/n)? " answer
Di bawah bash, readperintah 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
3. Beberapa trik untuk alat khusus
Kotak dialog yang lebih canggih, di luar yes - notujuan sederhana :
dialog --menu "Is this a good question"206012 y Yes n No m Maybe
Bilah kemajuan:
dialog --gauge "Filling the tank"20600<<(for i in{1..100};do
printf "XXX\n%d\n%(%a %b %T)T progress: %d\nXXX\n" $i -1 $i
sleep .033done)
Demo kecil:
#!/bin/shwhile true ;do[-x "$(which ${DIALOG%% *})"]|| DIALOG=dialog
DIALOG=$($DIALOG --menu "Which tool for next run?"2060122>&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 .0125done| $DIALOG --gauge "Filling the tank"20600
$DIALOG --infobox "This is a simple info box\n\nNo action required"2060
sleep 3if $DIALOG --yesno "Do you like this demo?"2060;thenAnsYesNo=Yes;elseAnsYesNo=No;fiAnsInput=$($DIALOG --inputbox "A text:"2060"Text here..."2>&1>/dev/tty)AnsPass=$($DIALOG --passwordbox "A secret:"2060"First..."2>&1>/dev/tty)
$DIALOG --textbox /etc/motd 2060AnsCkLst=$($DIALOG --checklist "Check some..."206012 \
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:"206012 \
" -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"2060done
#!/bin/bashset-i
HISTFILE=~/.myscript.history
history -c
history -r
myread(){
read -e -p '> ' $1
history -s ${!1}}
trap 'history -a;exit'01236while myread line;docase ${line%%*}in
exit )break;;*) echo "Doing something with '$line'";;esacdone
Ini akan membuat file .myscript.historydi Anda $HOMEdirektori, daripada Anda bisa menggunakan perintah sejarah readline ini, seperti Up, Down, Ctrl+ rdan lain-lain.
Perhatikan bahwa sttymenyediakan -gpilihan 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.
Jonathan Leffler
3
read answerakan menginterpretasikan garis miring terbalik sebelum spasi dan umpan garis, dan jika tidak stripkan yang jarang dimaksudkan. Gunakan read -r answersebagai gantinya sesuai SC2162 .
vlfig
1
Metode "Menggunakan riwayat readline" sangat tidak pantas untuk pertanyaan OP. Saya senang Anda memasukkannya juga. Saya memiliki puluhan skrip yang lebih rumit yang ingin saya perbarui dengan pola itu!
Bruno Bronosky
5
Anda dapat menggunakan caseuntuk 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 -qdengan benar) dan tidak memiliki panggilan sistem. ${answer#[Yy]}menggunakan ekspansi parameter untuk menghapus Yatau ydari awal $answer, menyebabkan ketidaksetaraan saat ada. Ini berfungsi di semua shell POSIX (tanda hubung, ksh, bash, zsh, busybox, dll).
Adam Katz
1
@CarterPape Ya, ini hanya lelucon! Tetapi dalam jawaban yang sulit ini, Anda mungkin menemukan banyak tips (poin kedua menyajikan setidaknya 3 metode berbeda)! Dan ... dari sekitar 5 tahun sekarang, Anda yang pertama tahu tentang metode penghitungan saya! ;-))
F. Hauri
349
echo "Please enter some input: "
read input_variable
echo "You entered: $input_variable"
Saya tidak setuju, karena hanya mengimplementasikan sebagian dari fungsi dialog 'Ya, Tidak, Batalkan' di DOS. Bagian yang gagal diimplementasikan adalah pemeriksaan input ... pengulangan sampai jawaban yang valid diterima.
Myrddin Emrys
1
(Judul pertanyaan aslinya adalah "Bagaimana cara saya meminta input dalam skrip shell Linux?")
Pistos
8
Tetapi uraian pertanyaan awal tidak berubah, dan selalu meminta tanggapan terhadap permintaan Ya / Tidak / Batalkan. Judul telah diperbarui agar lebih jelas daripada yang asli saya, tetapi deskripsi pertanyaan selalu jelas (menurut saya).
Myrddin Emrys
165
Anda dapat menggunakan perintah baca bawaan; Menggunakan-p opsi untuk meminta pengguna dengan pertanyaan.
Sejak BASH4, sekarang Anda dapat menggunakan -iuntuk menyarankan jawaban:
read -e -p "Enter the path to the file: "-i "/usr/local/etc/" FILEPATH
echo $FILEPATH
(Tapi ingat untuk menggunakan opsi "readline" -euntuk 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 ~/
Perlu dicatat bahwa itu FILEPATHadalah nama variabel yang Anda pilih, dan diatur dengan jawaban ke prompt perintah. Jadi jika Anda menjalankannya vlc "$FILEPATH", misalnya, vlcakan membuka file itu.
Ken Sharp
Apa manfaat dari -econtoh kedua (sederhana ya / tidak)?
JBallin
Ada alasan untuk menggunakannya, -e -pbukan -ep?
JBallin
1
Tanpa -etanda / 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.
+1 Solusi yang sangat sederhana. Satu-satunya hal: Ini akan meminta dan promt dan meminta ... sampai Anda menambahkan bagian exitdalam :)
kaiser
5
(kaiser: Untuk keluar darinya, cukup masukkan EOT:. Ctrl-DTapi tentu saja, kode nyata yang menggunakannya akan membutuhkan istirahat atau jalan keluar di tubuh.)
Zorawar
12
Namun, ini tidak akan memungkinkan Anda untuk memasukkan y atau n. Anda memilih dengan memasukkan 1 2 atau 3.
djjeck
3
exitakan keluar dari script bersama-sama, breakhanya akan keluar dari loop Anda (jika Anda berada di whileatau caseloop)
wranvaud
57
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
Letakkan empat spasi di awal setiap baris untuk mempertahankan pemformatan kode.
Jouni K. Seppänen
10
Mengapa kami menyediakan 'y' dan 'n' sebagai parameter untuk menanyakan () jika sakelar kasus di-hardcode? Itu hanya meminta penyalahgunaan. Mereka adalah parameter tetap, tidak dapat diubah, sehingga gema pada baris 2 harus berbunyi: echo -n "$ 1 [Y / T]?"
Myrddin Emrys
1
@MyrddinEmrys Bisakah Anda jelaskan komentar Anda? Atau memposting tautan ke artikel atau beberapa kata kunci sehingga saya bisa melakukan riset sendiri.
Mateusz Piotrowski
4
@MateuszPiotrowski Jawabannya telah diedit dan ditingkatkan sejak saya membuat komentar. Anda dapat mengklik tautan 'diedit 23 Des' di atas untuk melihat semua versi sebelumnya dari jawaban ini. Kembali pada tahun 2008, kodenya sangat berbeda.
Myrddin Emrys
27
Kamu ingin:
Perintah Bash builtin (yaitu portable)
Periksa TTY
Jawaban default
Waktu habis
Pertanyaan berwarna
Potongan
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_xxxxif[[ $do_xxxx =~^(y|Y|)$ ]]# Do if 'y' or 'Y' or emptythen
xxxx
fi
@ Simpan gema mencetak baris baru setelah respons Anda. Tanpanya, hal berikutnya yang akan dicetak akan muncul segera setelah respons Anda pada baris yang sama. Coba hapus echountuk melihat sendiri.
Dennis
13
Untuk mendapatkan inputbox ncurses-like yang bagus gunakan dialog perintah seperti ini:
#!/bin/bashif(dialog --title "Message"--yesno "Want to do something risky?"625)# message box will have the size 25x6 charactersthen
echo "Let's do something risky"# do something riskyelse
echo "Let's stay boring"fi
Paket dialog diinstal secara default setidaknya dengan SUSE Linux. Seperti:
ya, -e-ijangan bekerja di sh (Bourne shell), tetapi pertanyaannya ditandai bash khusus ..
Jahid
12
Anda dapat menggunakan default REPLYpada 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_MESSAGESkategori 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 answercase"$yn"in# match only work with the character class from the expression
${yesexpr##^}) echo "answer $yesstr" ;;
${noexpr##^}) echo "answer $nostr" ;;esac
Kata kunci yesstrdan nostrlokal serta item YESSTRdan NOSTRlanginfo sebelumnya digunakan untuk mencocokkan respons afirmatif dan negatif pengguna. Dalam POSIX.1-2008, yang yesexpr, noexpr, YESEXPR, dan NOEXPRdiperpanjang ekspresi reguler telah menggantikan mereka. Aplikasi harus menggunakan fasilitas perpesanan berbasis lokal umum untuk mengeluarkan pesan prompt yang menyertakan sampel respons yang diinginkan.
Saya suka penambahan opsi agnostik bahasa. Sudah selesai dilakukan dengan baik.
Myrddin Emrys
1
Sayangnya, POSIX hanya menentukan dua yang pertama (yesexpr dan noexpr). Di Ubuntu 16, yesstr dan nostr kosong.
Urhixidur
1
Tapi tunggu! Ada berita buruk! Ekspresi pernyataan kasus bash tidak teratur, mereka adalah ekspresi nama file. Jadi Ubuntu 16's yesexpr dan noexpr ("^ [yY]. *" Dan "^ [nN]. *", Masing-masing) akan gagal total karena periode tertanam. Dalam ekspresi reguler, ". *" Berarti "karakter non-baris baru, nol atau lebih banyak kali". Tetapi dalam pernyataan kasus, ini literal "." diikuti oleh sejumlah karakter.
Urhixidur
1
Akhirnya yang terbaik yang dapat dilakukan dengan yesexprdan noexprdalam lingkungan shell, adalah menggunakannya dalam pencocokan RegEx spesifik Bashif [[ "$yn" =~ $yesexpr ]]; then echo $"Answered yes"; else echo $"Answered no"; fi
Léa Gris
10
Hanya menekan tombol saja
Inilah pendekatan yang lebih panjang, tetapi dapat digunakan kembali dan modular:
Pengembalian 0= ya dan 1= tidak
Tidak perlu menekan enter - hanya satu karakter
Dapat menekan enteruntuk menerima pilihan default
Dapat menonaktifkan pilihan default untuk memaksakan suatu pilihan
Bekerja untuk keduanya zshdan bash.
Standarnya menjadi "tidak" saat menekan enter
Perhatikan bahwa Nhuruf kapital. Sini masuk ditekan, menerima default:
Di atas, saya hanya menekan enter, jadi perintahnya berlari.
Tidak ada default enter- memerlukan yataun
$ 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, 1atau false dikembalikan. Perhatikan bahwa dengan fungsi level yang lebih rendah ini Anda harus menyediakan [y/n]?prompt Anda sendiri .
Kode
# 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 defualtingfunction 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 entercase"$REPLY"in
Y|y)return0;;
N|n)return1;;'')[[ $enter_return ]]&&return"$enter_return"esacdone}# 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}
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/ttyberfungsi 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# Yeselse# Nofi
Bagian penting dari ini adalah validasi input. Saya pikir mengadaptasi contoh pertama saya untuk menerima ttyinput 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).
Myrddin Emrys
7
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:
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.
Salah satu cara sederhana untuk melakukan ini adalah dengan xargs -patau 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.)
Tidak buruk, tetapi xargs --interactiveterbatas 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.
Myrddin Emrys
Saya melihat. Pemikiran saya adalah bahwa "batal" dimaksudkan untuk menghentikan semua eksekusi lebih lanjut, yang didukung melalui Ctrl-C, tetapi jika Anda perlu melakukan sesuatu yang lebih kompleks pada membatalkan (atau tidak) ini tidak akan cukup.
Joshua Goldberg
3
Sebagai teman dari perintah satu baris saya menggunakan yang berikut:
Bisakah Anda mengklarifikasi penggunaan variabel prompt? Sepertinya saya dihapus setelah liner, jadi bagaimana Anda menggunakan garis untuk melakukan sesuatu?
Myrddin Emrys
prompt dihapus setelah loop sementara. Karena saya ingin variabel prompt diinisialisasi setelah itu (karena saya lebih sering menggunakan pernyataan). Memiliki baris ini dalam skrip shell hanya akan dilanjutkan jika y | Y diketik dan keluar jika n | N diketik atau ulangi meminta input untuk semua yang lain.
ccDict
3
Saya telah menggunakan casepernyataan itu beberapa kali dalam skenario seperti itu, menggunakan statment kasus adalah cara yang baik untuk menyelesaikannya. Sebuah whileloop, yang meng-ecapsulate caseblok, yang memanfaatkan kondisi boolean dapat diimplementasikan untuk memegang kendali lebih besar terhadap program, dan memenuhi banyak persyaratan lainnya. Setelah semua persyaratan telah terpenuhi, breakdapat 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: casepernyataan dan kemungkinan whileperulangan.
Contoh menggunakan casepernyataan 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
Ini tampaknya rumit dan rapuh. Bagaimana denganyn(){ read -s -n 1 -p '[y/n]'; test "$REPLY" = "y" ; } yn && echo success || echo failure
tripleee
2
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.";;esacdone
echo -e "\nAnswer = $ans"if[["${ans,,}"=="q"]];then
echo "OK Quitting, we will assume that he is"
exit 0fiif[["${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/43532read
perintah untuk memintaJawaban:
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:Metode lain, ditunjukkan oleh Steven Huwig , adalah
select
perintah Bash . Berikut adalah contoh yang sama menggunakanselect
: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 perluwhile 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:
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 .
sumber
exit
untukbreak
menjaga dari penutupan tab ketika saya memilih 'tidak'.break
diselect
jika tidak ada loop?Setidaknya lima jawaban untuk satu pertanyaan umum.
Bergantung kepada
dan jika kamu mau
1. Solusi generik POSIX
Anda bisa menggunakan
read
perintah, diikuti olehif ... then ... else
:(Terima kasih atas komentar Adam Katz : Mengganti tes di atas dengan yang lebih portabel dan menghindari satu garpu :)
POSIX, tetapi fitur kunci tunggal
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 .)
Catatan: Ini diuji di bawahSH, pesta, ksh, berlari dan busybox!
Sama, tetapi menunggu secara eksplisit untuk yatau n:
Menggunakan alat khusus
Ada banyak alat yang dibangun menggunakan
libncurses
,libgtk
,libqt
atau perpustakaan grafis lainnya. Misalnya, menggunakanwhiptail
:Bergantung pada sistem Anda, Anda mungkin perlu mengganti
whiptail
dengan alat serupa lainnya:di mana
20
tinggi kotak dialog dalam jumlah garis dan60
lebar kotak dialog. Semua alat ini memiliki sintaks yang hampir sama .2. Bash solusi spesifik
Metode garis dasar
Saya lebih suka menggunakan
case
sehingga saya bahkan bisa mengujiyes | ja | si | oui
jika diperlukan ...sejalan dengan fitur kunci tunggal
Di bawah bash, kita dapat menentukan panjang input yang dimaksudkan untuk
read
perintah:Di bawah bash,
read
perintah menerima parameter batas waktu , yang bisa berguna.3. Beberapa trik untuk alat khusus
Kotak dialog yang lebih canggih, di luar
yes - no
tujuan sederhana :Bilah kemajuan:
Demo kecil:
Lebih banyak sampel? Lihat Menggunakan whiptail untuk memilih perangkat USB dan pemilih penyimpanan yang dapat dilepas USB: USBKeyChooser
5. Menggunakan riwayat readline
Contoh:
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.sumber
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 denganstty -sane
.read answer
akan menginterpretasikan garis miring terbalik sebelum spasi dan umpan garis, dan jika tidak stripkan yang jarang dimaksudkan. Gunakanread -r answer
sebagai gantinya sesuai SC2162 .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 daripadaecho "$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 menghapusY
atauy
dari awal$answer
, menyebabkan ketidaksetaraan saat ada. Ini berfungsi di semua shell POSIX (tanda hubung, ksh, bash, zsh, busybox, dll).sumber
Anda dapat menggunakan perintah baca bawaan; Menggunakan
-p
opsi untuk meminta pengguna dengan pertanyaan.Sejak BASH4, sekarang Anda dapat menggunakan
-i
untuk menyarankan jawaban:(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:
sumber
FILEPATH
adalah nama variabel yang Anda pilih, dan diatur dengan jawaban ke prompt perintah. Jadi jika Anda menjalankannyavlc "$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.
sumber
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 diwhile
ataucase
loop)sumber
Inilah sesuatu yang saya kumpulkan:
Saya seorang pemula, jadi ambil ini dengan sebutir garam, tetapi sepertinya berhasil.
sumber
case $yn in
kecase ${yn:-$2} in
maka Anda dapat menggunakan argumen kedua sebagai nilai default, Y atau N.case $yn
kecase "${yn:-Y}"
memiliki ya sebagai defaultsumber
Kamu ingin:
Potongan
Penjelasan
[[ -t 0 ]] && read ...
=> Panggil perintahread
jika TTYread -n 1
=> Tunggu satu karakter$'\e[1;32m ... \e[0m '
=> Mencetak hijau(hijau baik-baik saja karena dapat dibaca pada latar belakang putih / hitam)
[[ $do_xxxx =~ ^(y|Y|)$ ]]
=> bash regexTimeout => Jawaban default adalah No
sumber
Cara termudah untuk mencapai ini dengan paling sedikit garis adalah sebagai berikut:
Ini
if
hanyalah sebuah contoh: terserah Anda bagaimana menangani variabel ini.sumber
Gunakan
read
perintah:dan kemudian semua hal lain yang Anda butuhkan
sumber
Solusi ini membaca satu karakter dan memanggil fungsi pada respons ya.
sumber
echo
untuk melihat sendiri.Untuk mendapatkan inputbox ncurses-like yang bagus gunakan dialog perintah seperti ini:
Paket dialog diinstal secara default setidaknya dengan SUSE Linux. Seperti:
sumber
Itu
-e
pilihan memungkinkan pengguna untuk mengedit masukan menggunakan tombol panah.Jika Anda ingin menggunakan saran sebagai masukan:
-i
opsi mencetak input sugestif.sumber
-e
-i
jangan bekerja di sh (Bourne shell), tetapi pertanyaannya ditandai bash khusus ..Anda dapat menggunakan default
REPLY
pada aread
, konversikan ke huruf kecil dan bandingkan dengan serangkaian variabel dengan ekspresi.Skrip juga mendukung
ja
/si
/oui
sumber
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.EDIT: Seperti yang disebutkan oleh @Urhixidur dalam komentarnya :
Lihat: https://www.ee.ryerson.ca/~courses/ele709/susv4/xrat/V4_xbd_chap07.html#tag_21_07_03_06
Atau menggunakan lokal dengan cara Bash:
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:sumber
yesexpr
dannoexpr
dalam lingkungan shell, adalah menggunakannya dalam pencocokan RegEx spesifik Bashif [[ "$yn" =~ $yesexpr ]]; then echo $"Answered yes"; else echo $"Answered no"; fi
Hanya menekan tombol saja
Inilah pendekatan yang lebih panjang, tetapi dapat digunakan kembali dan modular:
0
= ya dan1
= tidakzsh
danbash
.Standarnya menjadi "tidak" saat menekan enter
Perhatikan bahwa
N
huruf kapital. Sini masuk ditekan, menerima default:Perhatikan juga,
[y/N]?
itu ditambahkan secara otomatis. Default "tidak" diterima, jadi tidak ada yang digaungkan.Konfirmasikan kembali hingga respons yang valid diberikan:
Default ke "ya" saat menekan enter
Perhatikan bahwa
Y
huruf kapital:Di atas, saya hanya menekan enter, jadi perintahnya berlari.
Tidak ada default enter- memerlukan
y
ataun
Di sini,
1
atau false dikembalikan. Perhatikan bahwa dengan fungsi level yang lebih rendah ini Anda harus menyediakan[y/n]?
prompt Anda sendiri .Kode
sumber
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:Semoga ini bisa membantu seseorang.
sumber
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:
Metode ini diposting dengan harapan bahwa seseorang dapat menemukannya berguna dan menghemat waktu.
sumber
Versi pilihan ganda:
Contoh:
Ini akan diatur
REPLY
key
(di dalam skrip).sumber
Saya sarankan Anda menggunakan dialog ...
itu sederhana dan mudah digunakan, ada juga versi gnome yang disebut gdialog yang mengambil parameter yang sama persis, tetapi menunjukkannya gaya GUI di X.
sumber
Terinspirasi oleh jawaban @Mark dan @Myrddin saya membuat fungsi ini untuk prompt universal
gunakan seperti ini:
sumber
akan lebih umum:
sumber
Salah satu cara sederhana untuk melakukan ini adalah dengan
xargs -p
atau gnuparallel --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,
sumber
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:
Bentuk panjang tertulis, kerjanya seperti ini:
sumber
Saya telah menggunakan
case
pernyataan itu beberapa kali dalam skenario seperti itu, menggunakan statment kasus adalah cara yang baik untuk menyelesaikannya. Sebuahwhile
loop, yang meng-ecapsulatecase
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 kemungkinanwhile
perulangan.Contoh menggunakan
case
pernyataan untuk memenuhi permintaan Andasumber
Ya / Tidak / Batalkan
Fungsi
Pemakaian
Konfirmasikan dengan input pengguna yang bersih
Fungsi
Pemakaian
sumber
sumber
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.
sumber
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!
sumber