web-dev-qa-db-ja.com

シェルスクリプトでの使用方法や条件付き方法

スクリプトにifステートメントがあります。

次のようになります。

if [ "$a" != "0" -a "$b" != "100" ]; then
 #some commands here

私が間違っていない場合、上記の行は両方の条件が真であれば機能します。

では、some commandsを実行する前に、どちらか 1つまたは両方の条件が真であることをどのようにテストできますか?

3
cube00

標準(POSIX shおよびユーティリティ)の標準的な読みやすい方法は次のとおりです。

  • string比較:

    _if [ "$a" != 0 ] || [ "$b" != 100 ]; then...
    _
  • 10進整数の比較(0100は100です。先頭の空白が無視されるかどうかは、実装に依存します)。

    _if [ "$a" -ne 0 ] || [ "$b" -ne 100 ]; then...
    _
  • integerの比較(0x64、0144は100(一部のシェルでは8進数のPOSIXモードを有効にする必要があります)。シェルによっては100.0、1e2、50 + 50、(RANDOM時間の0.003%)...も同様です):

    _if [ "$((a != 0 || b != 100))" -ne 0 ]; then...
    _

    ただし、変数の内容によってその算術展開が構文エラーで失敗した場合は、シェルが異常終了するため、サブシェルでそれを実行してそのことを考慮する必要があります。

    _if ([ "$((a != 0 || b != 100))" -ne 0 ]); then
    _

    an任意のコマンド実行の脆弱性となるため、変数の内容が制御下にない場合は、とにかくこのフォームを使用しないでください)多くのシェルでbashkshzsh)(たとえば、x[$(reboot)]のように_$a_の値を使用)。

どちらを選択するかは、変数の内容が何であるか、および変数に何を許可するかによって異なります。正規の形式で10進整数が含まれていることがわかっている場合、3つすべてが同等になります。

いずれの場合も、_-a_/_-o_ test演算子 一般的には非推奨で信頼性が低い (コンテンツを制御している場合はここでは使用しない)は避けてください。ただし、変数の)。

10
[ "$((a||b^100))" -eq 1 ] && some commands

シェルの数学拡張は、ブール値&& AND || OR and ! NOT条件を、式を真の場合は1に、偽の場合は0に評価することで処理します。 。ビット単位の& AND | ORおよび^ XOR演算子も処理しますが、ここではそうであるように、ビット単位の式がブールevalのフィールドとして機能する場合がありますが、必ずしも0または1になるわけではありません。興味深いことに、シェルは~<<左と>>右シフト。

したがって、aがtrueの場合OR b^100がtrueの場合、展開評価は1になり、比較-eq[ test ]およびシェルは残りの&& some commandsを評価し続けます。

通常、この方法で整数を評価/比較する方が、一緒に文字列を作成するよりも簡単です...

... -a-oバイナリプライマリ()演算子[廃止]は廃止予定としてマークされています。 (それらを使用する多くの式は、評価される特定の式に応じて、文法によって曖昧に定義されます。)

(^ test仕様からの直接の引用)

それが機能する場合でも、正式に不特定の領域に入る前に、4を使用できます。

過去に、私はしばしば次のような小さな抽象化を適用することに有用性を見出しました:

math(){ return "$((!($1)))"; }

...次のように使用できます...

math 'a||b^100' && some commands

それは本当に私の考えではありませんでしたが、私は実際にPOSIX仕様の [〜#〜] xrat [〜#〜]Rationaleセクション:

... [i] tは、testコマンド[で大部分の関係演算テストを実行でき、シェル内の複雑な関係式を含むテストはまれですが、"$(())"自体の値をテストすることで対応できます。例えば:

    # a complicated relational expression
    while [ "$(( (($x + $y)/($a * $b)) < ($foo*$bar) ))" -ne 0 ] 

...さらに良いことに、多くの複雑な関係式を持つ珍しいスクリプトは、次のような関数を定義できます...

    val() { return "$((!$1))"; }

(ただし、上記の"quotesを追加しました。これらの人の何が問題になっていますか?)

1
mikeserv

あいまいさを避けるために、算術評価と括弧を使用します。

if (( ($a != 0)  || ($b != 100) )); then
# some commands

または、文字列も処理する場合は、[[を使用します。

1
muru

上で見たものよりも簡単な答え。

if [ "$a" != "0" -o "$b" != "100" ]; then
0
Otheus