GNU/Linux >> Linux の 問題 >  >> Linux

Linux シェル スクリプトで Yes/No/Cancel の入力を求めるにはどうすればよいですか?

1 つの一般的な質問に対して 5 つ以上の回答

に応じて

  • posix 準拠:一般的なシェル環境を備えた貧弱なシステムでも動作する可能性があります
  • bash 固有:いわゆる bashisms の使用

必要に応じて

  • 単純な「インライン」の質問/回答 (一般的な解決策)
  • ncurses や、libgtk や libqt を使用したよりグラフィカルなインターフェースなど、きれいにフォーマットされたインターフェース...
  • 強力な readline 履歴機能を使用

1. POSIX 汎用ソリューション

read を使用できます コマンドの後に 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

(Adam Katz のコメントに感謝:上記のテストを、より移植性が高く、1 つのフォークを回避するものに置き換えました:)

POSIX、ただし重要な機能は 1 つ

ただし、ユーザーが Return を押す必要がないようにしたい場合は、 、次のように書くことができます:

(編集: @JonathanLeffler が正しく示唆しているように、保存 stty の構成は、単に強制的に 正気 にするよりも優れている可能性があります .)

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

注: これは、sh、bash、ksh、dash、および busybox でテストされました!

同じですが、y を明示的に待機しています または 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

専用ツールの使用

libncurses を使用して構築された多くのツールがあります 、 libgtklibqt または他のグラフィカル ライブラリ。たとえば、 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 ...

2. Bash 固有のソリューション

基本インライン メソッド

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

3. 専用ツールのコツ

単純な 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

もっとサンプル? USB デバイスと USB リムーバブル ストレージ セレクターを選択するためのwhiptail の使用をご覧ください:USBKeyChooser

5. readline の履歴の使用

例:

#!/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 が作成されます あなたの $HOMEUp などの readline の履歴コマンドを使用するよりも、 、ダウン , Ctrl +r


シェル プロンプトでユーザー入力を取得する最も簡単で最も広く利用されている方法は、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

Steven Huwig が指摘したもう 1 つの方法は、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 は必要ありません。 無効な入力があった場合、ループして再試行します。

また、Léa Gris は、回答の中で言語にとらわれないリクエストを作成する方法を示しました。最初の例を複数の言語により適切に適応させると、次のようになります。

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

明らかに、他の通信文字列 (インストール、応答) はここでは未翻訳のままであり、より完全な翻訳で対処する必要がありますが、多くの場合、部分的な翻訳でも役立ちます。

最後に、F. Hauri による優れた回答をご覧ください。


echo "Please enter some input: "
read input_variable
echo "You entered: $input_variable"

Linux
  1. Linuxターミナルとシェルをクリスマス化する方法

  2. シェルスクリプトでバッファにデータを追加する方法は?

  3. Linux シェル スクリプトまたは変数の日付と時刻の書式設定

  1. LinuxBashシェルスクリプトで暗号化されたパスワードを使用する方法

  2. Linuxシェルスクリプトで数値と文字列を比較する方法

  3. Linux –画面上でスクリプトを実行する方法ロック/ロック解除?

  1. 入力が「はい」の場合、スクリプトを再実行しますか?

  2. Linuxスクリプトで端末のユーザー入力を隠す

  3. Linuxシェルスクリプトで正規表現を使用してファイルを検索する方法