2017-12-20 17 views
1

bash 스크립트에서 사용자에게 y/n 응답을 요구하는 경우가 있습니다. 필자는 종종이 스크립트를 단일 스크립트에서 여러 번 사용하기 때문에 사용자 입력이 Yes/No의 변형인지 확인한 다음이 대답을 "y"또는 "n"으로 정리하는 기능을 갖고 싶습니다. 이런 식으로 뭔가 :인수에서 명명 된 변수를 bash 함수로 변경하십시오.

yesno(){ 
    temp="" 
    if [[ "$1" =~ ^([Yy](es|ES)?|[Nn][Oo]?)$ ]] ; then 
     temp=$(echo "$1" | tr '[:upper:]' '[:lower:]' | sed 's/es//g' | sed 's/no//g') 
     break 
    else 
     echo "$1 is not a valid answer." 
    fi 
} 

I는 다음과 같은 기능을 사용하고 싶습니다 :

while read -p "Do you want to do this? " confirm; do # Here the user types "YES" 
    yesno $confirm 
done 
if [[ $confirm == "y" ]]; then 
    [do something] 
fi 

을 기본적으로,이 때 있도록 $confirm의 값을 첫 번째 인수의 값을 변경하려면 yesno 함수를 종료하면 $confirm이 "y"또는 "n"중 하나입니다.

yesno 함수 내에서 set -- "$temp"을 사용해 보았지만 제대로 작동하지 않습니다.

+0

이것은 X-Y 질문입니다. 문제는 제안 된 솔루션에 관한 것이고 OP는 실제로 해결 방법을 사용하여 문제를 해결하려고합니다. 허용 된 대답은 바깥 범위에서''$ 1 ''을 변경하지 않기 때문에 다른 사람들이 검색 결과로 찾으면 혼동을 일으킬 수 있습니다. 아마도 실제/즉각적인 문제를보다 자세히 설명하기 위해 질문을 편집해야합니다 ? –

+0

... 원래 제목을 기반으로 OP는'$ 1'의 내용에서 명명 된 변수 *의 값이 아니라'$ 1' 자체를 변경하는 방법을 알고 싶다고 생각했을 것입니다. –

답변

1

새 값을 출력하고 호출자의 변수를 덮어 쓰면됩니다.

yesno() { 
    if [[ "$1" =~ ^([Yy](es|ES)?|[Nn][Oo]?)$ ]] ; then 
     local answer=${1,,} 
     echo "${answer::1}" 
    else 
     echo "$1 is not a valid answer." >&2 
     echo "$1" # output the original value 
     return 1 # indicate failure in case the caller cares 
    fi 
} 

confirm=$(yesno "$confirm") 

그러나 좀 더 직접적인 접근 방법을 권하고 싶습니다. 즉,이 기능을 사용하여 메시지를 보내고 루핑합니다. 그 반복 된 논리를 모두 안으로 옮기십시오. 그렇다면 콜 사이트는 매우 간단합니다. 다음과 같이

confirm() { 
    local prompt=$1 
    local reply 

    while true; do 
     read -p "$prompt" reply 

     case ${reply,,} in 
      y*) return 0;; 
      n*) return 1;; 
      *) echo "$reply is not a valid answer." >&2;; 
     esac 
    done 
} 

if confirm "Do you want to do this? "; then 
    # Do it. 
else 
    # Don't do it. 
fi 

(. ${reply,,}는 소문자로 $reply 변환하는 떠들썩한 파티 -주의입니다)

+0

나중에 참조 할 때,'$ {reply ,,}'는 Bash 4 또는 그 이후 버전에서만 작동한다는 점에 유의해야한다. –

1

당신은 강타의 nameref 속성을 사용할 수 있습니다 (배쉬 4.3 이상이 필요합니다) :

#!/bin/bash 

yesno() { 
    # Declare arg as reference to argument provided 
    declare -n arg=$1 

    local re1='(y)(es)?' 
    local re2='(n)o?' 

    # Set to empty and return if no regex matches 
    [[ ${arg,,} =~ $re1 ]] || [[ ${arg,,} =~ $re2 ]] || { arg= && return; } 

    # Assign "y" or "n" to reference 
    arg=${BASH_REMATCH[1]} 
} 

while read -p "Prompt: " confirm; do 
    yesno confirm 
    echo "$confirm" 
done 

샘플 테스트 실행은 다음과 같습니다.

Prompt: YES 
y 
Prompt: nOoOoOo 
n 
Prompt: abc 

Prompt: 

표현식은 처음에 고정되어 있으므로 yessss 등도 모두 포함됩니다. 원하는 경우 끝 앵커 ($)를 추가 할 수 있습니다.

두 표현식이 일치하지 않으면 문자열이 비어있게 설정됩니다.