Git commit/checkoutを区別できるインテリジェントなエイリアスgc
を作成しています。
gc
が引数なしで、または-a
、-m
引数付きで呼び出されると、git commitが実行されます。それ以外の場合は、git checkoutが実行されます(追加の引数を持つb
フラグがある場合)。 gcの他のバリエーションが呼び出された場合、予期しない何かを行うのではなく、エラーをスローすることをお勧めします。
これが私のシェル関数です。
gc() {
args=$@
commit=false
checkout=false
# Check flags
while getopts ":am:b" opt; do
case $opt in
a|m)
commit=true
;;
b)
checkout=true
;;
\?)
echo "Unknown flags passed."
return 1
;;
esac
done
shift "$((OPTIND-1))"
# Check number of arguments
if [[ "$#" == 0 ]]; then
commit=true
Elif [[ "$#" == 1 ]]; then
checkout=true
else
echo "Too many arguments"
return 1
fi
# Finally run respective command
if [[ $commit == true && $checkout == true ]]; then
echo "Unable to ascertain which operation you would like to perform."
return 1
Elif [[ $commit == true ]]; then
git commit "$args"
Elif [[ $checkout == true ]]; then
git checkout "$args"
else
echo "Undefined behavior"
return 1
fi
}
ただし、これは正しく機能しません。少し実験したところ、別の変数に$@
を割り当てることが根本的な原因であることがわかりましたが、その理由と正確に何が間違っているのか理解できませんでした。
また、初めてシェル関数を作成するときは、自分が犯した間違いを強調してください。
$@
は配列です。配列に割り当てます。
args=("$@")
次に、それを配列として使用します。
Elif [[ $commit == true ]]; then
git commit "${args[@]}"
Elif [[ $checkout == true ]]; then
git checkout "${args[@]}"
else
現在のコードで起こっていることは、すべての個別の引数が単一の文字列として格納されていることです。だからあなたが呼び出す場合:
bc -a "foo bar"
これはargs
に次のように割り当てられます:
args='-a foo bar'
次に、実行する代わりに:
git commit -a "foo bar"
あなたが得る:
git commit '-a foo bar'
他の答えはPOSIXではないので、ここに代替案があります。位置の引数を一時的に破棄したい場合は、次のようにすることができます。
s1=$(printf '%s\n' "$@")
復元する準備ができたら、次の操作を行います。
IFS='
'
set -- $s1
これは、引数に改行が含まれていないことを前提としています。その場合は、別の区切り文字を使用する必要があります。
補足:気が付いたら、最後の行に引用符で囲まれていない変数が含まれています。これは、引用符で囲まれていない変数が許容される数少ないケースの1つです(私の意見では唯一のケース)。ユーザーが明示的にIFS
を設定した場合です。ユーザーは本質的に「はい、私はイムが何をしているか知っています。続行してください」と言います。