
私はこのコードを持っています:
#!/bin/bash
num=${1:-undefined}
cmd=$(which {banner,echo} | head -n1)
until [[ "$num" =~ ^[0-9]+$ ]]; do
read -p "Type a number: " num
done
for ((num;num>=0;num--)); do
$cmd $num
sleep 1
done
しかし、プログラムがインストールされているかどうかを知るより良い方法があると思います。私はこれを試しました。しかし、私はそれが明確ではないと思います。
which banner && cmd=banner || cmd=echo
cmd=$(eval 'which '{banner,echo}'||' :)
cmd=$(which {banner,echo} | head -n1)
cmd=$(which banner || which echo)
私は他のものよりも3を好むが、誰かがこれを行うための良い方法を見つけるのを助けることができると思いました。type
または必要に応じてhash
使用を受け入れます。command
これは簡潔なコードチャレンジなので、一行にして短く保ち、変数名やコマンド(||
、&&
などは除く)を繰り返さないようにしました。
答え1
関数ベースのアプローチは、最も明確なコードを生成します。少なくとも2つのバリエーションがあり、そのうちの1つはFloHimが上記のコメントで提案したものです(これは私の好きな方法ではありません)。
function myprint
{
if type banner >/dev/null
then banner "$@"
else echo "$@"
fi
}
myprint "Hello World!"
または - 私が好むバリアント - 使用条件付き関数の定義:
if type banner >/dev/null
then function myprint { banner "$@" ;}
else function myprint { echo "$@" ;}
fi
myprint "Hello World!"
if
呼び出しごとの条件付きオーバーヘッドがなく、文字列や変数式を繰り返す必要はありません(他の提案のように)。
答え2
最も簡単な方法は走ることです
command1 "hello world" || command2 "hello world"
最初のコマンドがないと、左側のコマンドが||
失敗するため、右側のコマンドが実行されます。なぜ最初にテストする必要があるのか理解できません。やってみて、失敗したら別のことをしてください。
不足しているコマンドによるエラーメッセージを無視して重複文字列を避けると、状況が少し良くなる可能性があります。
string="Hello world!"
banner "$string" || echo "$string"
コマンドが存在することを本当に確認する必要がある場合は、次のようにします。
command="banner"
type "$command" 2>/dev/null || command="echo"
"$command" "Hello world!"
答え3
zsh
コマンドをそのパスにマップする特別な連想配列で、$commands
次のことができます。
cmd=${commands[figlet]-${commands[banner]-echo}}
ユーティリティパスがある場合はそのパスに設定し、別のパスに設定し、両方がない場合(組み込み)に$cmd
設定します。figlet
banner
echo
figlet
banner
$cmd
変数()の代わりにコマンドを定義できます。
hash cmd=${commands[figlet]-${commands[banner]-$commands[echo]}}
echo
ここでは、組み込みユーティリティではなくスタンドアロンユーティリティで終わります。また、hash -r
akaではhashコマンドが消えますrehash
。