쉘 스크립트에서 입력을 일시 중지하고 사용자에게 선택을 요청하고 싶습니다.
표준 Yes
, No
또는 Cancel
유형 질문입니다.
일반적인 bash 프롬프트에서 이 작업을 어떻게 수행합니까?
질문자 :Myrddin Emrys
쉘 프롬프트에서 사용자 입력을 얻는 가장 간단하고 가장 널리 사용되는 방법은 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
분명히 다른 통신 문자열은 여기에서 번역되지 않은 채로 남아 있습니다(설치, 답변). 이는 더 완전한 번역에서 해결되어야 하지만 부분 번역이라도 많은 경우에 도움이 될 것입니다.
Myrddin Emrys
하나의 일반적인 질문에 대해 최소 5개의 답변.
에 따라
그리고 원한다면
- 간단한 ``in line'' 질문/답변(일반 솔루션)
- ncurses 또는 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
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
yesstr
및nostr
로케일 키워드와YESSTR
및NOSTR
langinfo 항목은 이전에 사용자의 긍정 및 부정 응답을 일치시키는 데 사용되었습니다. POSIX.1-2008에서는yesexpr
,noexpr
,YESEXPR
및NOEXPR
확장 정규식이 대체되었습니다. 애플리케이션은 일반 로케일 기반 메시징 기능을 사용하여 원하는 응답 샘플이 포함된 프롬프트 메시지를 발행해야 합니다.
또는 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
read
에 REPLY
를 사용하고 소문자로 변환하고 표현식을 사용하여 변수 세트와 비교할 수 있습니다.
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 키를 누릅니다 수
- 선택을 강제하기 위해 기본 선택을 비활성화할 수 있습니다
-
zsh
및bash
모두에서 작동합니다.
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 $
REPLY
를 y
(스크립트 내부)로 설정합니다.
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
'etc. > StackOverFlow' 카테고리의 다른 글
JavaScript에서 ==와 ===의 차이점 [중복] (0) | 2022.01.14 |
---|---|
div 내부에서 이미지를 세로로 정렬하는 방법 (0) | 2022.01.14 |
.gitignore는 Git에서 무시됩니다. (0) | 2022.01.14 |
가상 소멸자는 언제 사용합니까? (0) | 2022.01.14 |
Lodash와 Underscore.js의 차이점 (0) | 2022.01.14 |