私は初めてBashシェルスクリプトに触れ、次のコードを書いています。他の方法では動作できませんが、このコードは非常に粗雑なコードのようです。
誰かがこのコードを寛容な(安全で簡潔で読みやすい)Bashで書き直すのを手伝うことはできますか?特に、関数から値を返すより良い方法があるのか、ifステートメントでそれを正しくテストしているのか疑問に思います。 (if文に括弧を使用する必要がありますか?)
#!/bin/bash
input() {
read -p $'\e[31m\e[1m'"$1"$' [Y/n] \e[0m' -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]
then
return 0
fi
return 1
}
if input "Upgrade Arch?"
then
sudo pacman -Syu
fi
答え1
単に文で関数を終了すると、関数の戻りコードが文自体の戻りコードになります。
小切手が[[ $REPLY =~ ^[Yy]$ ]]
よさそうです。 bashに組み込まれている角かっこテストを使用しているため、変数内でトークン化が発生しないため、変数を引用する必要はありません。正規表現チェックを使用することをお勧めしますが、より単純なグローバルマッチングも[[ $REPLY = [Yy] ]]
機能します。
私がする主な変更点は、関数内でローカル変数を使用してそれをに渡すことですread
。これをatlocal
またはuseとマークするdeclare
と、関数内で変数をローカルで使用できます。
errexit
最後に、オプション(-e
)、nounset
()、およびスクリプトを有効にして-u
より安全にすることをお勧めします。pipefail
これは、コマンドが失敗した後にスクリプトが続行するのを防ぎ、変数名のタイプミスを見つけるのに役立ちます。このような場合は、より防御的にコーディングする必要がありますが(ほとんどのコマンドでバグを明示的にテストし、設定できない可能性がある環境変数にデフォルト値を使用する)、予期しない中断が発生したときにデバッグが簡単になります。
一緒に入れてください:
#!/bin/bash
set -eu -o pipefail
input() {
declare confirm
declare -r prompt=${1:-"Confirm?"}
read -p $'\e[31m\e[1m'"${prompt}"$' [Y/n] \e[0m' -n 1 -r confirm
echo
[[ $confirm =~ ^[Yy]$ ]]
}
if input "Upgrade Arch?" ; then
sudo pacman -Syu
fi
そして@StéphaneChazelas提案するとさらに改善することができます。
set -eu -o pipefail
input() {
declare confirm
declare -r prompt=${1:-"Confirm?"}
IFS= read -p $'\e[31;1m'"${prompt}"$' [Y/n] \e[m' -n 1 -r confirm
echo >&2
[[ $confirm = [Yy] ]]
}
if input "Upgrade Arch?" ; then
sudo pacman -Syu
fi