Bashで、コマンドまたはエイリアスに「Are you sure [Y / n]」を追加する方法を教えてください。


228

この特定のケースでは、Bashに確認を追加します

本気ですか?[はい/いいえ]

Mercurialのhg push ssh://username@www.example.com//somepath/morepath場合、これは実際にはエイリアスです。それを実現するためにエイリアスに追加できる標準コマンドはありますか?

その理由は、ということであるhg pushhg out類似した音ができ、私が欲しいとき時々hgoutrepo、私はaccidentlly入力することhgpushrepo(両方とも別名です)。

更新:それが次のような別のコマンドを含む組み込みコマンドのようなものである可能性がある場合:confirm && hg push ssh://...それは素晴らしいでしょう... yesまたはnoを要求し、残りの場合は続行できるコマンドだけですyes


1
おそらくエイリアスの代わりに関数を使いたいでしょう。From info bash:「ほとんどすべての目的で、エイリアスよりもシェル関数が優先されます。」
追って通知があるまで一時停止。

本当に?ls -lまたはのようなものでもrm -i
非極性

5
ほとんどすべてのではなく、すべての。ところで、のようなこと絶対にないでくださいalias rm='rm -i'。ある日、最も必要なときにエイリアスが存在せず、boom!重要なものが失われます。
追って通知があるまで一時停止。

のエイリアスrm -iがない場合は、シェルスクリプトを使用することもできません。だからいつもいつもタイプrm -iするの?
2010

8
それは習慣についてです。私の以前のコメントのようなエイリアスを作成して、入力rmして-i動作を期待する習慣を身に付けることができます。その後、ある日、エイリアスが存在しません(何らかの理由で、エイリアスが設定されていないか、設定されていないか、別のシステムにいます)と入力するrmと、確認なしですぐに削除されます。おっとっと!ただし、alias askrm='rm -i'「コマンドが見つかりません」というエラーが発生するため、このようにエイリアスを作成した場合は問題ありません。
追って通知があるまで一時停止。

回答:


332

これらは、ハミッシュの答えのよりコンパクトで多目的な形式です。大文字と小文字の混合を処理します。

read -r -p "Are you sure? [y/N] " response
case "$response" in
    [yY][eE][sS]|[yY]) 
        do_something
        ;;
    *)
        do_something_else
        ;;
esac

または、Bash> =バージョン3.2の場合:

read -r -p "Are you sure? [y/N] " response
if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]
then
    do_something
else
    do_something_else
fi

注:$responseが空の文字列の場合、エラーが発生します。修正するには、単に引用符を追加します"$response"。–文字列を含む変数では常に二重引用符を使用します(例:"$@"代わりに使用することをお勧めします$@)。

または、Bash 4.x:

read -r -p "Are you sure? [y/N] " response
response=${response,,}    # tolower
if [[ "$response" =~ ^(yes|y)$ ]]
...

編集:

あなたの編集に応じて、confirmこれが私の答えの最初のバージョンに基づいてコマンドを作成して使用する方法です(他の2つでも同様に機能します)。

confirm() {
    # call with a prompt string or use a default
    read -r -p "${1:-Are you sure? [y/N]} " response
    case "$response" in
        [yY][eE][sS]|[yY]) 
            true
            ;;
        *)
            false
            ;;
    esac
}

この機能を使用するには:

confirm && hg push ssh://..

または

confirm "Would you really like to do a push?" && hg push ssh://..

9
実際のテストでは、[Y / N]ではなく[Y / N]である必要があります。
Simon A. Eugster

not equal to2番目の例を確認する場合は、$response変数をキャストする必要があることを述べておきます。例:if [[ ! $response =~ ^([yY][eE][sS]|[yY])$ ]]
ジョアン・クーニャ

@JoãoCunha:=~正規表現一致演算子なので、「等しくない」ではなく「一致しない」になります。
追って通知があるまで一時停止。

@DennisWilliamson正解、それが私が意味しようとしたことです。何らかの理由でコメントを編集できません。
ジョアン・クーニャ

6
いい汎用yes / no機能。強力なプロンプトをサポートし、オプションで「y」または「n」をデフォルトにします。
wkw 2015

19

おおまかなスニペットは次のとおりです。議論を転送する方法を見つけましょう。

read -p "Are you sure you want to continue? <y/N> " prompt
if [[ $prompt == "y" || $prompt == "Y" || $prompt == "yes" || $prompt == "Yes" ]]
then
  # http://stackoverflow.com/questions/1537673/how-do-i-forward-parameters-to-other-command-in-bash-script
else
  exit 0
fi

気を付けろyes | command name here:)


13

確認はキャリッジリターンで簡単にバイパスされます。有効な入力を求めるプロンプトを継続的に表示すると便利です。

これを簡単にする関数があります。Y | Nが受信されない場合、「無効な入力」が赤で表示され、ユーザーに再度プロンプトが表示されます。

prompt_confirm() {
  while true; do
    read -r -n 1 -p "${1:-Continue?} [y/n]: " REPLY
    case $REPLY in
      [yY]) echo ; return 0 ;;
      [nN]) echo ; return 1 ;;
      *) printf " \033[31m %s \n\033[0m" "invalid input"
    esac 
  done  
}

# example usage
prompt_confirm "Overwrite File?" || exit 0

引数を渡すことでデフォルトのプロンプトを変更できます


12

「yes」のこれらのバリアントを明示的にチェックしないようにするには、正規表現でbash正規表現演算子「=〜」を使用できます。

read -p "Are you sure you want to continue? <y/N> " prompt
if [[ $prompt =~ [yY](es)* ]]
then
(etc...)

これは、ユーザー入力が「y」または「Y」で始まり、その後にゼロ個以上の「es」が続くかどうかをテストします。


5

これはハックかもしれません:

問題のように Unix / Bashでは、「xargs -p」はコマンドを実行する前に確認を求める良い方法ですか?

私たちxargsは仕事をするために使うことができます:

echo ssh://username@www.example.com//somepath/morepath | xargs -p hg push

もちろん、これは次のようにエイリアスとして設定されます hgpushrepo

例:

$ echo foo | xargs -p ls -l
ls -l foo?...y
-rw-r--r--  1 mikelee    staff  0 Nov 23 10:38 foo

$ echo foo | xargs -p ls -l
ls -l foo?...n

$

4

以下を/ etc / bashrcファイルに追加します。このスクリプトは、「確認」というエイリアスではなく、常駐の「関数」を追加します。


function confirm( )
{
#alert the user what they are about to do.
echo "About to $@....";
#confirm with the user
read -r -p "Are you sure? [Y/n]" response
case "$response" in
    [yY][eE][sS]|[yY]) 
              #if yes, then execute the passed parameters
               "$@"
               ;;
    *)
              #Otherwise exit...
              echo "ciao..."
              exit
              ;;
esac
}

いいね。ただし、いくつかのマイナーな修正:二重引用符を囲ん$response$@誤解を避けるために、いくつかの冗長なセミコロンがあり、*条件は終了するのではなく、戻る必要があります。
Gordon Davisson、2013

明確にするために、不要なのはいくつかのステートメントの最後にある単一のセミコロンです。
追って通知があるまで一時停止。

4

これは少し短すぎるかもしれませんが、私自身の個人的な使用では、うまく機能します

read -n 1 -p "Push master upstream? [Y/n] " reply; 
if [ "$reply" != "" ]; then echo; fi
if [ "$reply" = "${reply#[Nn]}" ]; then
    git push upstream master
fi

read -n 11文字を読み取るだけです。Enterキーを押す必要はありません。「n」または「N」ではない場合、「Y」と見なされます。Enterキーを押すだけでYも意味します。

(本当の質問については:bashスクリプトを作成し、エイリアスを変更して、以前に指していたものではなく、そのスクリプトを指すようにします)


短くて甘い、ちょうど私が必要なもの。ありがとう!
Raymo111

3
read -r -p "Are you sure? [Y/n]" response
  response=${response,,} # tolower
  if [[ $response =~ ^(yes|y| ) ]] || [[ -z $response ]]; then
      your-action-here
  fi

つまり、スペース文字は「はい」を意味しますか?
Xen2050

「はい」または「はい」を除くすべてがアクションを確認するので、あなたは正しいです!@ xen2050
SergioAraujo 2017

3

Enterキーを押す必要はありません

これは、より長く、再利用可能なモジュール式のアプローチです。

  • 0= yesおよび1= noを返します
  • 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 *

Enterキーを押すと、デフォルトで「はい」に設定されます

Yが大文字であることに注意してください:

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

上記では、Enterキーを押しただけなので、コマンドが実行されました。

デフォルトではありませんenter-必須yまたはn

$ get_yes_keypress "Here you cannot press enter. Do you like this"
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 a y/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
}

2

さて、これconfirmがJamesのバージョンから変更されたの私のバージョンです。

function confirm() {
  local response msg="${1:-Are you sure} (y/[n])? "; shift
  read -r $* -p "$msg" response || echo
  case "$response" in
  [yY][eE][sS]|[yY]) return 0 ;;
  *) return 1 ;;
  esac
}

これらの変更は次のとおりです。

  1. local変数名の衝突を防ぐために使用します
  2. read$2 $3 ...そのアクションを制御するために使用するので-n-t
  3. read正常に終了しない場合はecho、美容のための改行
  4. Git on Windowsだけ持っていないbash-3.1と何も持っているtrueか、falseそう使用し、return代わりに。もちろん、これはbash-4.4(Git for Windowsの現在のバージョン)とも互換性があります。
  5. IPythonスタイルの「(y / [n])」を使用して、「n」がデフォルトであることを明確に示します。

2

このバージョンでは、複数のケースyまたはYnまたは、N

  1. オプション:承認の質問が提供されるまで質問を繰り返します

  2. 必要に応じて、他の回答を無視します

  3. オプション:必要に応じてターミナルを終了します

    confirm() {
        echo -n "Continue? y or n? "
        read REPLY
        case $REPLY in
        [Yy]) echo 'yup y' ;; # you can change what you do here for instance
        [Nn]) break ;;        # exit case statement gracefully
        # Here are a few optional options to choose between
        # Any other answer:
    
        # 1. Repeat the question
        *) confirm ;;
    
        # 2. ignore
        # *) ;;
    
        # 3. Exit terminal
        # *) exit ;;
    
        esac
        # REPLY=''
    }

これにも注意してください。この関数の最後の行で、REPLY変数をクリアします。それ以外の場合echo $REPLYは、ターミナルを開いたり閉じたりするか、再度設定するまで、設定されたままです。


1

ゲームに遅れましたが、私confirmは以前の回答の関数のさらに別のバリアントを作成しました:

confirm ()
{
    read -r -p "$(echo $@) ? [y/N] " YESNO

    if [ "$YESNO" != "y" ]; then
        echo >&2 "Aborting"
        exit 1
    fi

    CMD="$1"
    shift

    while [ -n "$1" ]; do
        echo -en "$1\0"
        shift
    done | xargs -0 "$CMD" || exit $?
}

それを使用するには:

confirm your_command

特徴:

  • コマンドをプロンプトの一部として出力します
  • NULL区切り文字を使用して引数を渡します
  • コマンドの終了状態を保持します

バグ:

  • echo -en で動作します bashますが、シェルで失敗する可能性があります
  • 引数が干渉すると失敗する可能性があります echoまたはにxargs
  • シェルスクリプティングは難しいため、他にも膨大な数のバグ

1

試して、

 #!/bin/bash
 pause ()
 {
 REPLY=Y
 while [ "$REPLY" == "Y" ] || [ "$REPLY" != "y" ]
 do
  echo -e "\t\tPress 'y' to continue\t\t\tPress 'n' to quit"
  read -n1 -s
      case "$REPLY" in
      "n")  exit                      ;;
      "N")  echo "case sensitive!!"   ;; 
      "y")  clear                     ;;
      "Y")  echo "case sensitive!!"   ;;
      * )  echo "$REPLY is Invalid Option"     ;;
 esac
 done
 }
 pause
 echo "Hi"

0

これは、正確にではなく、単なるハック「yesまたはnoを求めて」:別名はhg push ...しないようにhgpushrepoするのではなくhgpushrepoconfirmedpush、私は、全体の事を綴ることができ、時間によって、左脳は論理的な選択をしました。


1
しかし、あなたはあなたがTAB鍵を使うことを知っています!
Hamish Grubijan、2013

わかりました、本当ですが、少なくとも私はコマンドをちらっと見て、それが奇妙であることを確認し、Enterキーを
押す

0

同じではありませんが、とにかく機能するアイデア。

#!/bin/bash  
i='y'  
while [ ${i:0:1} != n ]  
do  
    # Command(s)  
    read -p " Again? Y/n " i  
    [[ ${#i} -eq 0 ]] && i='y'  
done  

出力:
もう一度?Y / n N
もう一度?Y / n何
かありますか?Y / n 7
もう一度?Y / n&
もう一度?Y / n nsijf
$

$ i読み取りの最初の文字のみをチェックするようになりました。


0

以下のコードは2つのものを組み合わせています

  1. shopt -s大文字小文字を区別しないnocasematch

  2. 両方の入力を受け入れる条件の場合、yes、Yes、YES、yのいずれかを渡します。

    shopt -s nocasematch

    if [[sed-4.2.2。$ LINE =〜(yes | y)$]]

    次に0を終了します

    fi


0

これがローカライズされた正規表現を使用する私のソリューションです。したがって、ドイツ語でも「Ja」の「j」は「yes」と解釈されます。

最初の引数は質問です。2番目の引数が「y」の場合、yesよりもデフォルトの回答になります。それ以外の場合、デフォルトの回答はありません。答えが「はい」の場合の戻り値は0で、答えが「いいえ」の場合の戻り値は1です。

function shure(){
    if [ $# -gt 1 ] && [[ "$2" =~ ^[yY]*$ ]] ; then
        arg="[Y/n]"
        reg=$(locale noexpr)
        default=(0 1)
    else
        arg="[y/N]"
        reg=$(locale yesexpr)
        default=(1 0)
    fi
    read -p "$1 ${arg}? : " answer
    [[ "$answer" =~ $reg ]] && return ${default[1]} || return ${default[0]}
}

こちらが基本的な使い方です

# basic example default is no
shure "question message" && echo "answer yes" || echo "answer no"
# print "question message [y/N]? : "

# basic example default set to yes
shure "question message" y && echo "answer yes" || echo "answer no"
# print "question message [Y/n]? : "
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.