linux मैं लिनक्स खोल स्क्रिप्ट में हां/नहीं/रद्द इनपुट के लिए कैसे संकेत करूं?




bash shell (20)

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

मैं एक शेल स्क्रिप्ट में इनपुट रोकना चाहता हूं, और उपयोगकर्ता को विकल्पों के लिए संकेत देता हूं। मानक 'हां, नहीं, या रद्द करें' प्रकार का प्रश्न। मैं इसे एक विशिष्ट बाश प्रॉम्प्ट में कैसे पूरा करूं?


यहां कुछ ऐसा है जो मैंने एक साथ रखा है:

#!/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

मैं एक नौसिखिया हूँ, इसलिए नमक के अनाज के साथ इसे ले लो, लेकिन ऐसा लगता है कि यह काम करता है।


हां / नहीं / रद्द करें

समारोह

#!/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

तुम्हें चाहिए:

  • बैश बिल्टिन कमांड (यानी पोर्टेबल)
  • टीटीवी जांचें
  • डिफ़ॉल्ट उत्तर
  • समय समाप्त
  • रंगीन सवाल

टुकड़ा

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 ... => टीटीवी अगर कॉल कमांड read
  • read -n 1 => एक वर्ण की प्रतीक्षा करें
  • $'\e[1;32m ... \e[0m ' => हरे रंग में प्रिंट करें
    (हरा ठीक है क्योंकि सफेद / काले दोनों पृष्ठभूमि पर पठनीय)
  • [[ $do_xxxx =~ ^(y|Y|)$ ]] => बैश रेगेक्स

टाइमआउट => डिफ़ॉल्ट उत्तर नहीं है

do_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

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?"

...

आप अंतर्निहित read कमांड का उपयोग कर सकते हैं; उपयोगकर्ता को एक प्रश्न के साथ संकेत देने के लिए -p विकल्प का उपयोग करें।

बीएएसएच 4 के बाद से, अब आप उत्तर का सुझाव देने के लिए -i का उपयोग कर सकते हैं, इसलिए उपयोगकर्ता को इसे दर्ज करने के लिए केवल प्रेस को दबा देना होगा:

read -e -p "Enter the path to the file: " -i "/usr/local/etc/" FILEPATH
echo $FILEPATH

(लेकिन "रीडलाइन" विकल्प का उपयोग करना याद रखें- तीर कुंजियों के साथ लाइन संपादन की अनुमति देने के लिए)


मैंने case स्टेटमेंट का इस्तेमाल इस तरह के परिदृश्य में दो बार किया है, case स्टेटमेंट का उपयोग करने के लिए इसका एक अच्छा तरीका है। एक while लूप, जो case ब्लॉक को पार करता है, जो कि बूलियन स्थिति का उपयोग करता है, कार्यक्रम के और भी नियंत्रण को पकड़ने के लिए लागू किया जा सकता है, और कई अन्य आवश्यकताओं को पूरा करता है। सभी शर्तों को पूरा करने के बाद, एक break का उपयोग किया जा सकता है जो प्रोग्राम के मुख्य भाग पर नियंत्रण को वापस कर देगा। इसके अलावा, अन्य स्थितियों को पूरा करने के लिए, निश्चित रूप से नियंत्रण संरचनाओं के साथ सशर्त बयान जोड़ा जा सकता है: case स्टेटमेंट और लूप के while संभव है।

आपके अनुरोध को पूरा करने के लिए case स्टेटमेंट का उपयोग करने का उदाहरण

#! /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

एक सामान्य प्रश्न के लिए कम से कम पांच जवाब।

इस पर निर्भर करते हुए

  • posix अनुपालन: जेनेरिक shell वातावरण के साथ खराब सिस्टम पर काम कर सकता है
  • bash विशिष्ट: तथाकथित bashisms का उपयोग कर

और यदि आप चाहते हैं

  • सरल '`लाइन में' प्रश्न / उत्तर (जेनेरिक समाधान)
  • सुंदर प्रारूपित इंटरफेस, जैसे ncurses या libgtk या libqt का उपयोग कर अधिक ग्राफिकल ...
  • शक्तिशाली रीडलाइन इतिहास क्षमता का उपयोग करें

1. POSIX जेनेरिक समाधान

आप read कमांड का उपयोग कर सकते हैं, उसके बाद 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

POSIX, लेकिन एकल कुंजी सुविधा

लेकिन अगर आप नहीं चाहते कि उपयोगकर्ता को रिटर्न हिट करना पड़े, तो आप लिख सकते हैं:

( संपादित: जैसा कि @ जोनाथन लेफ्लर सही तरीके से सुझाव देते हैं, स्टटी की कॉन्फ़िगरेशन को सहेजने से उन्हें बेहतर बनाने के लिए मजबूर होना बेहतर हो सकता है।)

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

नोट: यह sh , bash , ksh , dash और busybox अंतर्गत परीक्षण किया गया था!

वही, लेकिन वाई या एन के लिए स्पष्ट रूप से इंतजार कर रहा है:

#/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

समर्पित उपकरणों का उपयोग करना

libncurses , libgtk , libqt या अन्य ग्राफिकल पुस्तकालयों का उपयोग करके बनाए गए कई टूल हैं। उदाहरण के लिए, 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. बैश विशिष्ट समाधान

लाइन विधि में मूल

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 लिए भी परीक्षण कर सकता हूं yes | ja | si | oui अगर जरूरत पड़ती है ...

एकल कुंजी सुविधा के साथ लाइन में

बैश के तहत, हम read आदेश के लिए इच्छित इनपुट की लंबाई निर्दिष्ट कर सकते हैं:

read -n 1 -p "Is this a good question (y/n)? " answer

बैश के तहत, कमांड कमांड एक टाइमआउट पैरामीटर स्वीकार करता है, जो उपयोगी हो सकता है।

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

समर्पित उपकरणों के लिए कुछ चालें

सरल yes - no से परे अधिक परिष्कृत संवाद बॉक्स yes - no उद्देश्य 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

5. रीडलाइन के इतिहास का उपयोग करना

उदाहरण:

#!/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

इससे आपकी $HOME निर्देशिका में एक फ़ाइल। .myscript.history जाएगी, आप रीडलाइन के इतिहास कमांड का उपयोग कर सकते हैं, जैसे ऊपर , नीचे , Ctrl + r और अन्य।


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

read -e -p "Enter your choice: " choice

-e विकल्प उपयोगकर्ता को तीर कुंजियों का उपयोग करके इनपुट संपादित करने में सक्षम बनाता है।

यदि आप इनपुट के रूप में सुझाव का उपयोग करना चाहते हैं:

read -e -i "yes" -p "Enter your choice: " choice

-i विकल्प एक सूचक इनपुट मुद्रित करता है।


अधिक सामान्य होगा:

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
}

बैश ने इस उद्देश्य के लिए select किया है।

select result in Yes No Cancel
do
    echo $result
done

ऐसी पुरानी पोस्ट पर पोस्ट करने के लिए खेद है। कुछ हफ्ते पहले मुझे एक ही समस्या का सामना करना पड़ रहा था, मेरे मामले में मुझे एक समाधान की आवश्यकता थी जो ऑनलाइन इंस्टॉलर-स्क्रिप्ट के भीतर भी काम करता था, उदाहरण के लिए: curl -Ss https://raw.github.com/_____/installer.sh | bash curl -Ss https://raw.github.com/_____/installer.sh | bash

read yesno < /dev/tty का उपयोग करना मेरे लिए ठीक है:

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

उम्मीद है कि यह किसी की मदद करता है।


एक लाइन कमांड के दोस्त के रूप में मैंने निम्नलिखित का उपयोग किया:

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=;

लिखित लम्बाई, यह इस तरह काम करता है:

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=;

यह समाधान एक एकल चरित्र को पढ़ता है और हां प्रतिक्रिया पर एक फ़ंक्शन को कॉल करता है।

read -p "Are you sure? (y/n) " -n 1
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
    do_something      
fi

कम से कम लाइनों के साथ इसे प्राप्त करने का सबसे आसान तरीका निम्नानुसार है:

read -p "<Your Friendly Message here> : y/n/cancel" CONDITION;

if [ "$CONDITION" == "y" ]; then
   # do something here!
fi

if यह सिर्फ एक उदाहरण है: यह आपके ऊपर है कि इस चर को कैसे संभालें।


read कमांड का प्रयोग करें:

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

और फिर आपको आवश्यक सभी अन्य सामान


ऐसा करने का एक आसान तरीका xargs -p या gnu parallel --interactive

मुझे xargs के व्यवहार को थोड़ा बेहतर पसंद है क्योंकि यह अंत में चलाने के लिए yesses को इकट्ठा करने के बजाय, अन्य इंटरैक्टिव यूनिक्स कमांड जैसे प्रॉम्प्ट के तुरंत बाद प्रत्येक कमांड निष्पादित करता है। (आप जो चाहते थे उसके माध्यम से प्राप्त करने के बाद आप Ctrl-C कर सकते हैं।)

जैसे,

echo *.xml | xargs -p -n 1 -J {} mv {} backup/

@ मार्क और @ मिरडिन के उत्तरों से प्रेरित मैंने इस समारोह को सार्वभौमिक संकेत के लिए बनाया है

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
}

इस तरह इसका इस्तेमाल करें:

unipromtp "Select an option: (a)-Do one (x)->Do two (f)->Do three : " "a x f" selection
echo "$selection"

मेरा सुझाव है कि आप संवाद का उपयोग करें ...

लिनक्स अपरेंटिस: संवाद का उपयोग करके बैश शैल स्क्रिप्ट को बेहतर बनाएं

संवाद कमांड अपने उपयोग को अधिक इंटरैक्टिव बनाने के लिए शेल स्क्रिप्ट में विंडो बक्से के उपयोग को सक्षम बनाता है।

यह सरल और उपयोग करने में आसान है, यहां एक जीनोम संस्करण भी है जिसे gdialog कहा जाता है जो सटीक समान पैरामीटर लेता है, लेकिन यह एक्स पर जीयूआई शैली दिखाता है।





scripting