私の関数で$#が常にゼロであるのはなぜですか?

私の関数で$#が常にゼロであるのはなぜですか?

Bashが私を狂わせています。次の(そして例からコピーして貼り付けた数十のバリエーション)がうまくいかない理由はわかりません。

#!/bin/bash

echo $#

function main {
    if (( $# < 1 )); then
        usage
    fi

    echo "good"
}

function usage {
    echo "Usage: $0 <outputdir>"
    exit 1
}

main

パラメータを渡し、$#期待どおりに設定されていることがはっきりとわかりますが、何らかの理由でパラメータチェックは毎回失敗します。

答え1

mainパラメータなしで関数を呼び出しています。したがって、$#メイン関数では常に0です。

各関数インスタンスには固有のパラメータがあります。 (「インスタンス」は、関数が(再帰呼び出しによって)複数回呼び出されると、各呼び出しに固有のパラメータがあることを意味します。)位置パラメータ$1など$2および関連パラメータは$#関数呼び出しを$*参照します。$@たとえば、main foo bar関数内でthenを呼び出すと、値は2にmainなります。$1foo$#

スクリプトから関数に引数を渡すには、を使用します"$@"。この構文は、スクリプト(または関数内で呼び出された場合は関数)に渡された引数のリストに展開されます。通常、二重引用符で発生するのとは異なり、引数は単一の"$@"文字列ではなく文字列のリストとして個別に渡されます。二重引用符が必要です。それ以外の場合、引数はそのまま渡されず、スペースで区切られたファイル名パターンのリストとして扱われます。

function main {
  if (( $# < 1 )); then
    usage
  fi
  echo "good"
}
main "$@"

答え2

これは働きます:

#!/bin/bash
set -x
NARGS=$#

function main {
    if [ $NARGS -lt 1 ]; then
        usage
    fi

    echo good
}

function usage {
    echo "Usage: $0 <outputdir>"
    exit 1
}

main

私はset -xわざわざそこを去った。これらのエラーをデバッグすると便利です。main関数に引数を渡さないと、$#関数内でゼロになります($NARGSこの内容を表示するには条件でwithに置き換えます)。$#if

関連情報