etc./StackOverFlow

Linux 셸 스크립트에서 예/아니오/취소 입력을 묻는 메시지를 표시하려면 어떻게 합니까?

청렴결백한 만능 재주꾼 2022. 1. 14. 12:32
반응형

질문자 :Myrddin Emrys


쉘 스크립트에서 입력을 일시 중지하고 사용자에게 선택을 요청하고 싶습니다.
표준 Yes , No 또는 Cancel 유형 질문입니다.
일반적인 bash 프롬프트에서 이 작업을 어떻게 수행합니까?



쉘 프롬프트에서 사용자 입력을 얻는 가장 간단하고 가장 널리 사용되는 방법은 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가 지적한 또 다른 방법은 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) yesptrn="$1"; noptrn="$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 의 훌륭한 답변 을 확인하십시오.


Myrddin Emrys

하나의 일반적인 질문에 대해 최소 5개의 답변.

에 따라

그리고 원한다면

  • 간단한 ``in line'' 질문/답변(일반 솔루션)
  • 또는 libgtk 또는 libqt를 사용하는 더 많은 그래픽과 같은 꽤 형식화된 인터페이스...
  • 강력한 readline 기록 기능 사용

1. POSIX 일반 솔루션

read 명령을 if ... then ... else 사용할 수 있습니다.

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

 # if echo "$answer" | grep -iq "^y" ;then


Community Wiki

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

Pistos

내장된 읽기 명령을 사용할 수 있습니다. -p 옵션을 사용하여 사용자에게 질문을 프롬프트합니다.

BASH4 이후로 이제 -i 를 사용하여 답변을 제안할 수 있습니다.

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

(그러나 화살표 키로 줄 편집을 허용 -e 를 사용하는 것을 기억하십시오)

"예/아니오" 논리를 원하면 다음과 같이 할 수 있습니다.

 read -e -p " List the content of your home dir ? [Y/n] " YN [[ $YN == "y" || $YN == "Y" || $YN == "" ]] && ls -la ~/

yPhil

Bash는 이 목적을 위해 선택했습니다.

 select result in Yes No Cancel do echo $result done

Steven Huwig

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

serg

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

SumoRunner

여기에 내가 정리한 것이 있습니다.

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

나는 초보자이므로 이것을 소금 한 알과 함께 섭취하지만 효과가있는 것 같습니다.


mpen

당신이 원하는:

  • Bash 내장 명령(즉, 이식 가능)
  • TTY 확인
  • 기본 답변
  • 시간 초과
  • 컬러 질문

단편

 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 ... => TTY인 경우 read
  • read -n 1 => 한 문자를 기다립니다.
  • $'\e[1;32m ... \e[0m ' => 녹색으로 인쇄
    (녹색은 흰색/검정색 배경 모두에서 읽을 수 있으므로 괜찮습니다.)
  • [[ $do_xxxx =~ ^(y|Y|)$ ]] => bash 정규식

시간 초과 => 기본 대답은 아니오입니다.

 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

oHo

최소한의 라인으로 이를 달성하는 가장 쉬운 방법은 다음과 같습니다.

 read -p "<Your Friendly Message here> : y/n/cancel" CONDITION; if [ "$CONDITION" == "y" ]; then # do something here! fi

if 는 예시일 뿐입니다. 이 변수를 어떻게 처리할지는 여러분의 몫입니다.


Apurv Nerlekar

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

그리고 당신이 필요로 하는 다른 모든 것들


ThatLinuxGuy

이 솔루션은 단일 문자를 읽고 yes 응답에 대한 함수를 호출합니다.

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

Dennis

멋진 ncurses와 같은 입력 상자를 얻으려면 다음과 같은 명령 대화 상자를 사용하십시오.

 #!/bin/bash if (dialog --title "Message" --yesno "Want to do something risky?" 6 25) # message box will have the size 25x6 characters then echo "Let's do something risky" # do something risky else echo "Let's stay boring" fi

대화 패키지는 기본적으로 최소한 SUSE Linux와 함께 설치됩니다. 다음과 같이 보입니다. 작동 중인 "대화 상자" 명령


Thorsten Staerk

POSIX 셸에서 로케일 인식 "예/아니오 선택"을 처리할 수 있습니다. LC_MESSAGES 로케일 범주의 항목을 사용하여 witch는 입력과 일치하는 기성 RegEx 패턴과 현지화된 Yes No에 대한 문자열을 제공합니다.

 #!/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 answer case "$yn" in # match only work with the character class from the expression ${yesexpr##^}) echo "answer $yesstr" ;; ${noexpr##^}) echo "answer $nostr" ;; esac

편집 : @Urhixidur 가 그의 의견 에서 언급했듯이 :

불행히도 POSIX는 처음 두 개(yesexpr 및 noexpr)만 지정합니다. Ubuntu 16에서 yesstr 및 nostr은 비어 있습니다.

참조: https://www.ee.ryerson.ca/~courses/ele709/susv4/xrat/V4_xbd_chap07.html#tag_21_07_03_06

LC_MESSAGES

yesstrnostr 로케일 키워드와 YESSTRNOSTR langinfo 항목은 이전에 사용자의 긍정 및 부정 응답을 일치시키는 데 사용되었습니다. POSIX.1-2008에서는 yesexpr , noexpr , YESEXPRNOEXPR 확장 정규식이 대체되었습니다. 애플리케이션은 일반 로케일 기반 메시징 기능을 사용하여 원하는 응답 샘플이 포함된 프롬프트 메시지를 발행해야 합니다.

또는 Bash 방식으로 로케일을 사용합니다.

 #!/usr/bin/env bash IFS=$'\n' read -r -d '' yesexpr noexpr _ < <(locale LC_MESSAGES) printf -v yes_or_no_regex "(%s)|(%s)" "$yesexpr" "$noexpr" printf -v prompt $"Please answer Yes (%s) or No (%s): " "$yesexpr" "$noexpr" declare -- answer=; until [[ "$answer" =~ $yes_or_no_regex ]]; do read -rp "$prompt" answer done if [[ -n "${BASH_REMATCH[1]}" ]]; then echo $"You answered: Yes" else echo $"No, was your answer." fi

답변은 로케일 환경에서 제공하는 정규 표현식을 사용하여 일치합니다.

나머지 메시지를 번역하려면 bash --dump-po-strings scriptname 을 사용하여 현지화를 위한 po 문자열을 출력합니다.

 #: scriptname:8 msgid "Please answer Yes (%s) or No (%s): " msgstr "" #: scriptname:17 msgid "You answered: Yes" msgstr "" #: scriptname:19 msgid "No, was your answer." msgstr ""

Léa Gris

제 경우에는 다운로드한 스크립트(예: curl -Ss https://example.com/installer.sh | sh

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

user9869932

readREPLY 를 사용하고 소문자로 변환하고 표현식을 사용하여 변수 세트와 비교할 수 있습니다.
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

Walter A

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

-e 옵션을 사용하면 화살표 키를 사용하여 입력을 편집할 수 있습니다.

제안을 입력으로 사용하려면:

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

-i 옵션은 암시적인 입력을 인쇄합니다.


Jahid

단일 키 누르기 전용

다음은 더 길지만 재사용 가능한 모듈식 접근 방식입니다.

  • 0 = 예 및 1 = 아니오를 반환합니다.
  • Enter 키를 누를 필요 없음 - 한 문자만 가능
  • 기본 선택을 수락 enter 키를 누릅니다 수
  • 선택을 강제하기 위해 기본 선택을 비활성화할 수 있습니다
  • zshbash 모두에서 작동합니다.

Enter 키를 누를 때 기본값은 "아니오"입니다.

N 은 대문자로 표시됩니다. 여기에서 Enter 키를 누르면 기본값이 적용됩니다.

 $ confirm "Show dangerous command" && echo "rm *" Show dangerous command [y/N]?

또한 [y/N]? 자동으로 추가되었습니다. 기본 "no"가 허용되므로 아무 것도 에코되지 않습니다.

유효한 응답이 제공될 때까지 다시 확인:

 $ confirm "Show dangerous command" && echo "rm *" Show dangerous command [y/N]? X Show dangerous command [y/N]? y rm *

엔터를 누를 때 기본값은 "예"입니다.

Y 는 대문자로 표시됩니다.

 $ confirm_yes "Show dangerous command" && echo "rm *" Show dangerous command [Y/n]? rm *

위에서 방금 Enter 키를 눌렀으므로 명령이 실행되었습니다.

입력 시 기본값 없음 - y 또는 n

 $ 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

여기에서 1 또는 false가 반환되었습니다. 이 하위 수준 기능을 사용하면 자신의 [y/n]? 즉각적인.

암호

 # 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 ay/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 defualting function 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 enter case "$REPLY" in Y|y) return 0;; N|n) return 1;; '') [[ $enter_return ]] && return "$enter_return" esac done } # 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 }

Tom Hale

나는 아무도 그런 간단한 사용자 입력에 대해 여러 줄 에코 메뉴를 보여주는 답변을 게시하지 않았음을 알아차렸으므로 여기에 내가 가보겠습니다.

 #!/bin/bash function ask_user() { echo -e " #~~~~~~~~~~~~# | 1.) Yes | | 2.) No | | 3.) Quit | #~~~~~~~~~~~~#\n" read -e -p "Select 1: " choice if [ "$choice" == "1" ]; then do_something elif [ "$choice" == "2" ]; then do_something_else elif [ "$choice" == "3" ]; then clear && exit 0 else echo "Please select 1, 2, or 3." && sleep 3 clear && ask_user fi } ask_user

이 방법은 누군가가 유용하고 시간을 절약할 수 있기를 바라는 마음에서 게시되었습니다.


Yokai

객관식 버전:

 ask () { # $1=question $2=options # set REPLY # options: x=..|y=.. while $(true); do printf '%s [%s] ' "$1" "$2" stty cbreak REPLY=$(dd if=/dev/tty bs=1 count=1 2> /dev/null) stty -cbreak test "$REPLY" != "$(printf '\n')" && printf '\n' ( IFS='|' for o in $2; do if [ "$REPLY" = "${o%%=*}" ]; then printf '\n' break fi done ) | grep ^ > /dev/null && return done }

예시:

 $ ask 'continue?' 'y=yes|n=no|m=maybe' continue? [y=yes|n=no|m=maybe] g continue? [y=yes|n=no|m=maybe] k continue? [y=yes|n=no|m=maybe] y $

REPLYy (스크립트 내부)로 설정합니다.


Ernest A

@Mark 및 @Myrddin의 답변에서 영감을 받아 범용 프롬프트를 위해 이 기능을 만들었습니다.

 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 : " "axf" selection echo "$selection"

Miguel

더 일반적인 것은 다음과 같습니다.

 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 }

Alexander Löfqvist

yn() { if [[ 'y' == `read -s -n 1 -p "[y/n]: " Y; echo $Y` ]]; then eval $1; else eval $2; fi } yn 'echo yes' 'echo no' yn 'echo absent no function works too!'

jlettvin

나는 당신이 대화 를 사용하는 것이 좋습니다 ...

Linux 견습생: 대화 상자를 사용하여 Bash 셸 스크립트 개선

dialog 명령을 사용하면 쉘 스크립트에서 창 상자를 사용하여 대화식으로 사용할 수 있습니다.

간단하고 사용하기 쉽습니다. 정확히 동일한 매개변수를 사용하지만 X에서 GUI 스타일을 보여주는 gdialog라는 gnome 버전도 있습니다.


Osama Al-Maadeed

이를 수행하는 한 가지 간단한 방법은 xargs -p 또는 gnu parallel --interactive 입니다.

나는 xargs가 마지막에 실행할 yesses를 수집하는 대신 다른 대화형 유닉스 명령과 마찬가지로 프롬프트 직후에 각 명령을 실행하기 때문에 xargs의 동작을 조금 더 좋아합니다. (원하는 것을 통과한 후에 Ctrl-C를 할 수 있습니다.)

예,

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

Joshua Goldberg

한 줄 명령의 친구로서 다음을 사용했습니다.

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

ccDict

case 문을 두 번 사용했는데, case 문을 사용하는 것이 좋은 방법입니다. case 블록을 캡슐화하는 while 루프는 프로그램을 더 많이 제어하고 다른 많은 요구 사항을 충족하기 위해 구현될 수 있습니다. 모든 조건이 충족된 후 프로그램의 주요 부분으로 제어를 다시 전달 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, eg /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

oOpSgEo

예 / 아니오 / 취소

기능

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

Eduardo Cuomo

이것은 내가 일반적으로 스크립트/함수에 필요한 것입니다.

  • 기본 대답은 예입니다. Enter 키를 누르면
  • z도 수락하십시오 (혼합하는 경우 QWERTZ 레이아웃에 있음)
  • 다른 언어 허용("ja", "Oui", ...)
  • 함수 내부에 있는 경우 올바른 종료를 처리합니다.
 while true; do read -p "Continue [Y/n]? " -n 1 -r -e yn case "${yn:-Y}" in [YyZzOoJj]* ) echo; break ;; [Nn]* ) [[ "$0" = "$BASH_SOURCE" ]] && exit 1 || return 1 ;; # handle exits from shell or function but don't exit interactive shell * ) echo "Please answer yes or no.";; esac done echo "and off we go!"

rubo77

가장 간단한 솔루션은 영리한 트릭이 없는 이 한 줄짜리입니다.

 read -p "press enter ..." y

그것은 어떤 키가 아니라 Enter 키를 기다리는 것을 제외하고는 고전적인 DOS Hit any key to continue

사실, 이것은 예 아니오 취소에 대한 세 가지 옵션을 제공하지 않지만 control-C를 No resp로 수락할 때 유용합니다. 다음과 같은 간단한 스크립트에서 취소:

 #!/bin/sh echo Backup this project read -p "press enter ..." y rsync -tavz . /media/hard_to_remember_path/backup/projects/yourproject/

못생긴 명령과 경로를 기억할 필요가 없지만 실행하려는 스크립트가 아니라고 결정하기 전에 중지할 기회를 주지 않고 너무 빨리 실행되는 스크립트는 기억하고 싶지 않기 때문입니다.


Roland

출처 : http:www.stackoverflow.com/questions/226703/how-do-i-prompt-for-yes-no-cancel-input-in-a-linux-shell-script

반응형