シェルスクリプトから関数を呼び出す

シェルスクリプトから関数を呼び出す

いくつかの条件に応じて、0または1を返す単純な関数をシェルに書きました。関数名をfooとします。

foo(){

...

...

}

ここで、以下のようにif条件でfooを呼び出そうとします。

if ( foo $1 )

...

..

うまくいきます。ただし、次の方法を使用して呼び出すとエラーが発生します。

if [ foo $1 ]

...

...

「単項演算子の予測」エラーが発生するのはなぜですか?

答え1

あなたが使用するとき:

if ( foo $1 )

サブシェルfoo $1で実行し、if終了状態に応じて動作します。

あなたが使用するとき:

if [ foo $1 ]

シェルを使用しようとしていますtest金持ち有効なテスト演算子ではありません。有効なテスト演算子を見つけることができますここ


あなたの質問と必ずしも関連があるわけではありませんが、特にシェルテスト角かっこ内で常に変数を引用する必要があります。何かが存在する限り、シェルテストは成功します。したがって、有効なテスト演算子を使用しても不要な結果が生じる可能性があります。

$ unset var
$ [ -n $var ] && echo yes
yes
$ [ -n "$var" ] && echo yes
$ [ -n "" ] && echo yes
$ [ -n ] && echo yes
yes
$ [ foo ] && echo yes
yes
$ [ foo bar ] && echo yes
-bash: [: foo: unary operator expected

シェルテストでは、単一の文字列の存在は、2つ以上の文字列が存在し、文字列の1つが有効なテスト演算子である場合はtrueと評価されます。

答え2

ifステートメントはコマンドの終了状態を処理します。関数はreturn状態で終了するか、文字列をエコーする必要があります。あなたの目的にはreturnより適切に見えます。関数が正常に完了した場合は0を返し、エラーが発生した場合は別の値を返します。例:

$ foo(){ [ -e '/etc/passwd' ] && return 0;  }
$ if foo; then echo "/etc/passwd exists"; fi
/etc/passwd exists

実際には、同じコマンドであり、エラーが発生したかどうかを示すためにゼロまたはゼロ以外の終了状態を返すので、 とはまったく同じことがよく見られることif [ ... ]; then...に注意してください。if test ...; then...[test

答え3

他のユーザーが言ったことに加えて、if複合コマンドの実際の構文は次のとおりです。

if compound_list
then compound_list
[elif compound_list
then compound_list]...
[else compound_list]
fi

デフォルトでは、はcompound_list複数のコマンドのリストです。if最初のコマンドの後に続く最後のコマンドの終了コードを調べて、COMPOUND_LIST実行する項目(、、またはいずれかthen ...)を決定します。elif ...; then ...else ...

つまり、次のように書き換えることができます。

if foo "$1"; then
  # Code to execute if foo returns 0
else
  # Code to execute if foo returns 1
fi

以下を使用することをお勧めしfooます。23254255case

foo "$1"

case "$?" in
  0) # Code to execute if foo returns 0 ;;
  1) # Code to execute if foo returns 1 ;;
  2) # Code to execute if foo returns 2 ;;
  3) # Code to execute if foo returns 3 ;;
  ...
  254) # Code to execute if foo returns 254 ;;
  255) # Code to execute if foo returns 255 ;;
esac

編集1

構文で「$1」を定義した後に「;」はありますか?

はい、Kusalalanandaが言ったように、コマンドの区切り文字として使用されます。

POSIXの定義次のコマンド:

  • 簡単なコマンド:[assignments] program [arguments] [redirections]
  • 管路:[!] command [pipe_operator command]...
  • リスト:
    • ANDまたはリスト:pipeline [and-or_list_operator pipeline]...
    • 化合物リスト:and-or_list [compound_list_operator and-or_list]
  • 複合コマンド:
    • グループ化コマンド:
      • ( compound_list )
      • { compound_list; }
    • のための:for name [in words]; do compound_list; done
    • ケース:case word in [[(] patterns ) compound_list ;;]... esac
    • 場合:if compound_list; then compound_list; [elif compound_list; then compound_list;]... [else compound_list;] fi
    • しかし:while compound_list; do compound_list; done
    • まで:until compound_list; do compound_list; done
  • 機能定義コマンド:name() compound_command [redirections]

Aはcompound_list_operatorセミコロンまたは改行文字であり、//compound_listコンテキストforで使用されます。caseifwhileuntil

{ compound_list; }コマンドの最後のコマンドが閉じ括弧compound_listと同じ行にある場合でも、}セミコロンが必要です。

関連情報