ソーススクリプトに渡されたパラメータが無効です。

ソーススクリプトに渡されたパラメータが無効です。

渡された引数の数を確認し、誤った場合に警告するAIXのスクリプト: -

if [ "$#" -ge 1 ]; then
  ...
else
  echo 'Usage: myscript <a> [b] [c]'
fi

スクリプトはそれを取得するためにいくつかの環境変数を設定します。つまり、コマンドラインに次のように入力します。 2番目のスクリプトはありません。他のスクリプトからスクリプトをインポートしません。

. ./myscript.sh

引数を渡さない場合は、usingステートメントを印刷したいのですが、前のコマンドに渡された引数を使用して実行します(必ずしもこのスクリプトである必要はありません!)。

これを再確認するために、スクリプトの先頭に次の行を追加して、これが真実であることを証明しました。

echo $# $@

パラメータを渡さないと、以前のソーススクリプトのパラメータ数とリストが印刷されます。

0個の引数を渡して再インポートするときに0になるにはどうすればよいですか$#

可能な最小の再作成はスクリプトなので:-

myscript.sh

echo $# $@

それから実行してください: -

. ./myscript.sh a b c

印刷する

3 a b c

その後、引数なしで再実行してください。

. ./myscript.sh

同じ結果を出力する

3 a b c

印刷すると予想される場合

0

スクリプトを取得できず、直接実行する場合:-

./myscript.sh

その後、期待どおりに動作し、印刷されます。

0

これが現在の問題を明確にすることを願っています。

上記の方法がなぜ機能しないのかを説明する答えはたくさんあり、どうすべきかに対する答えはないようで、もう一度試してみて、私が何をしたいのかを説明しなければならないと思いました。

必要

少なくとも1つの引数を必要とするスクリプトを作成し、その引数として呼び出されない場合は文句を言います(上記の質問の最初のコード部分を参照)、スクリプトはいくつかの環境変数を設定する必要があります。 2番目の要件のため、スクリプトが完了したときに環境変数が設定され続けるようにスクリプトをインポートする必要があるとします。パラメータが渡されていない時期を伝え、環境変数も設定するスクリプトをどのように作成しますか?

答え1

存在する

. path/to/script at least one argument

他の人が言ったように、シェルによっては、これらの追加パラメータは無視されるか(Bourne、Almquist)、スクリプトが解釈されたときに現在の位置パラメータセット($@、、$1...)を置き換えます(他のほとんどのシェル)。$2POSIXは、追加の引数がに渡されるときの動作を指定しません.。この場合、set a bスクリプトの位置パラメータ(たとえば)への変更が完了後も保持されるかどうかについて、シェル間に若干の違いがあります.

存在する:

. path/to/script

ただし、動作が指定されます。位置パラメータが必要です。いいえ影響を受けるため、スクリプトの解釈は以前と同じままです。

このスクリプトの解釈中に位置パラメータを空のリストにするには、事前にリセットするか、次の関数を使用する必要があります。

set -- # or shift "$#"
. path/to/script

(位置パラメータは失われますが)または次の機能を使用してください。

dot() { file=$1; shift; . "$file"; }
dot path/to/myscript

コマンドを実行すると、.位置パラメーターは関数の位置パラメーターになります。後でshift関数に渡される引数から最初の引数を引いた値になるので、上記は空のリストですが、これは関数を使用すると、任意の引数リストをソーススクリプトに渡すことができることを意味します。

dot path/to/myscript extra args

これはソーススクリプトで提供されていますextra args$1$2

myscript呼び出しが位置引数のリストを変更すると、関数の位置引数のみがset影響を受け、これらの変更は関数が返された後も保持されません。

答え2

バッシュヘルプテキスト.

.: . filename [arguments]
    Execute commands from a file in the current shell.

    Read and execute commands from FILENAME in the current shell.  The
    entries in $PATH are used to find the directory containing FILENAME.
    If any ARGUMENTS are supplied, they become the positional parameters
    when FILENAME is executed.

この文章に注意してください: "もし引数を指定しないでください。」引数が指定されていない場合、現在の位置引数は保持されます。

$ cat /tmp/sourceme.sh     
printf "%d: " "$#"
printf "<%s> " "$@"
printf "\n"
$ bash -c 'set -- aa bb; . /tmp/sourceme.sh'
2: <aa> <bb> 
$ bash -c 'set -- aa bb; . /tmp/sourceme.sh foo bar'
2: <foo> <bar> 

私がテストした他のすべてのシェル(zsh、ksh)も同様に機能します。を除いてdashいつも元の位置パラメータを保持します。

$ dash -c 'set -- aa bb; . /tmp/sourceme.sh foo bar'
2: <aa> <bb> 

位置パラメータのリセットに関する言及はありません。POSIXの定義..だから最初から議論をするのは非標準的なようです。


関数は標準シェルの引数を受け入れるため、ソーススクリプトの代わりに関数を使用できます。この場合、関数を定義するファイルを取得します。

define_fun.shたとえば、関数定義を含むファイル():

#!/bin/sh
f() {
    echo "args: $# $@"     # just a test
    if [ "$#" = 0 ]; then 
        echo please give at least one argument
        return 1
    fi;
    ENVVAR=$1          # this should be visible to the whole shell  
    export ENVVAR      # and any commands called later
} 

その後、使用してください。

$ . define_fun.sh      # source the file to load the func in the current shell

$ f                    # actually run it: this'll complain
$ f 123 456            # this should set ENVVAR
$ echo $ENVVAR         # and this will print '123'

シェルの初期化ファイルの1つに関数定義を配置できます(~/.profile?はシェルによって異なります)。

答え3

dot組み込みコマンドに引数を渡すことはKornシェル拡張であり、他のシェルでは許可されていません。

POSIX 標準では、ドットコマンドについて $# と $@ を参照していないので、現在のシェルのパラメータはドットコマンドに表示されるので、次のようにシェルを呼び出すと:

myshell -s a b c

それから電話してください

. ./myscript.sh

印刷する予定です

3 a b c

関連情報