GNU/Linux >> Belajar Linux >  >> Linux

Bagaimana saya meminta input Ya/Tidak/Batalkan dalam skrip shell Linux?

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"

Linux
  1. Bagaimana Cara Menambahkan Data Ke Buffer Dalam Script Shell?

  2. Dapatkan Script Untuk Berjalan Lagi Jika Input Ya?

  3. Format tanggal dan waktu untuk skrip atau variabel shell Linux

  1. Menyembunyikan input pengguna di terminal dalam skrip Linux

  2. Cara mencari file menggunakan regex di skrip shell linux

  3. Bagaimana cara membuat skrip tanggapan ya untuk menginstal program?

  1. Cara Mempercantik Terminal dan Shell Linux Anda

  2. Cara Menggunakan Kata Sandi Terenkripsi di Linux Bash Shell Script

  3. Bagaimana Membandingkan Angka dan String di Linux Shell Script