2017-12-20 28 views
1

私のbashスクリプトでは、y/nの回答を求めるプロンプトが表示されることがよくあります。私はこのスクリプトを1回のスクリプトで何度も使用することが多いので、ユーザーの入力が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 
} 

私は、次のように機能を使用したい:

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"のいずれかです。

機能内でset -- "$temp"を使ってみましたが、動作させることができません。

+0

これは非常に多くのX-Y質問です。問題は解決策を使用したいという問題とは対照的に、提案された解決策に関する質問です。受け入れられた答えは外部スコープ内で '' $ 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に変換bashのイズムである)

+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なども同様にカウントされます。これが望ましくない場合は、終了アンカー($)を追加することができます。

どちらの式も一致しない場合、文字列は空に設定されます。

関連する問題