Setidaknya lima jawaban untuk satu pertanyaan umum.
Tergantung pada
- mematuhi posix:dapat bekerja pada sistem yang buruk dengan lingkungan shell generik
- khusus bash:menggunakan apa yang disebut bashisme
dan jika Anda mau
- pertanyaan/jawaban ``sejalan'' sederhana (solusi umum)
- antarmuka yang diformat cantik, seperti ncurses atau lebih grafis menggunakan libgtk atau libqt...
- gunakan kemampuan riwayat readline yang andal
1. solusi umum POSIX
Anda bisa menggunakan read
perintah, diikuti dengan if ... then ... else
:
printf 'Is this a good question (y/n)? '
read answer
# if echo "$answer" | grep -iq "^y" ;then
if [ "$answer" != "${answer#[Yy]}" ] ;then # this grammar (the #[] operator) means that the variable $answer where any Y or y in 1st position will be dropped if they exist.
echo Yes
else
echo No
fi
(Berkat 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 Kembali , Anda dapat menulis:
(Diedit: Seperti yang disarankan oleh @JonathanLeffler, hemat konfigurasi stty bisa lebih baik daripada hanya memaksa mereka untuk waras .)
printf '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 telah diuji di bawah sh, bash, ksh, dash, dan busybox!
Sama, tetapi menunggu secara eksplisit untuk y atau n :
#/bin/sh
printf '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
Menggunakan alat khusus
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
Tergantung 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
adalah tinggi kotak dialog dalam jumlah baris dan 60
adalah lebar kotak dialog. Semua alat ini memiliki hampir sama sintaksis.
DIALOG=whiptail
if [ -x /usr/bin/gdialog ] ;then DIALOG=gdialog ; fi
if [ -x /usr/bin/xdialog ] ;then DIALOG=xdialog ; fi
...
$DIALOG --yesno ...
2. Bash solusi khusus
Dasar sesuai metode
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
jadi saya bahkan bisa menguji yes | ja | si | oui
jika diperlukan...
berbaris dengan kunci tunggal fitur
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 batas waktu parameter, yang mungkin 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, melebihi yes - no
sederhana tujuan:
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 USB yang dapat dilepas:USBKeyChooser
5. Menggunakan riwayat readline
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 $HOME
Anda direktori, daripada Anda dapat menggunakan perintah riwayat readline, seperti Naik , Bawah , Ctrl +r dan lainnya.
Metode paling sederhana dan paling banyak tersedia untuk mendapatkan input pengguna pada prompt shell adalah read
memerintah. Cara terbaik untuk mengilustrasikan 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, yang ditunjukkan oleh Steven Huwig, adalah select
Bash memerintah. 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 menampilkan pilihan yang tersedia, dan Anda mengetikkan angka yang sesuai dengan pilihan Anda. Itu juga berulang secara otomatis, jadi tidak perlu while true
loop untuk mencoba lagi jika mereka memberikan masukan yang tidak valid.
Juga, Léa Gris mendemonstrasikan cara untuk membuat bahasa permintaan agnostik dalam jawabannya. Mengadaptasi contoh pertama saya untuk melayani beberapa bahasa dengan lebih baik mungkin terlihat seperti ini:
set -- $(locale LC_MESSAGES)
yesexpr="$1"; noexpr="$2"; yesword="$3"; noword="$4"
while true; do
read -p "Install (${yesword} / ${noword})? " yn
if [[ "$yn" =~ $yesexpr ]]; then make install; exit; fi
if [[ "$yn" =~ $noexpr ]]; then exit; fi
echo "Answer ${yesword} / ${noword}."
done
Jelas string komunikasi lainnya tetap tidak diterjemahkan di sini (Instal, Jawab) yang perlu ditangani dalam terjemahan yang lebih lengkap, tetapi bahkan terjemahan sebagian akan sangat membantu dalam banyak kasus.
Terakhir, silakan lihat jawaban yang sangat bagus dari F. Hauri.
echo "Please enter some input: "
read input_variable
echo "You entered: $input_variable"