1. ホーム
  2. shell

シェルスクリプトから関数をインポートする

2023-08-05 12:08:36

質問

shUnitでテストしたいシェルスクリプトがあります。スクリプト(およびすべての関数)は、インストールがはるかに簡単になるため、単一のファイルになっています。

の例です。 script.sh

#!/bin/sh

foo () { ... }
bar () { ... }

code

で定義された関数をテストするために、(配布やインストールを必要としない)2番目のファイルを書きたかったのです。 script.sh

次のようなものです。 run_tests.sh

#!/bin/sh

. script.sh

# Unit tests

さて、問題は . (または source をBashで使うこともできます)。関数定義のパースだけでなく、スクリプト内のコードも実行されます。

引数なしのスクリプトは何も悪いことをしないので、私は

. script.sh > /dev/null 2>&1

が、私の目的を達成するためにもっと良い方法がないかと考えていました。

編集

私の提案した回避策は、ソース・スクリプトが exit を呼び出す場合は動作しないので、終了をトラップする必要があります。

#!/bin/sh

trap run_tests ERR EXIT

run_tests() {
   ...
}

. script.sh

run_tests 関数は呼び出されますが、ソースコマンドの出力をリダイレクトするとすぐに、スクリプト内の関数は解析されず、トラップハンドラで利用できなくなります。

これは動作しますが、出力される script.sh :

#!/bin/sh
trap run_tests ERR EXIT
run_tests() {
   function_defined_in_script_sh
}
. script.sh

これでは出力はされませんが、関数が定義されていないというエラーが出ます。

#!/bin/sh
trap run_tests ERR EXIT
run_tests() {
   function_defined_in_script_sh
}
. script.sh | grep OUTPUT_THAT_DOES_NOT_EXISTS

これでは出力されず run_tests トラップハンドラは全く呼ばれません。

#!/bin/sh
trap run_tests ERR EXIT
run_tests() {
   function_defined_in_script_sh
}
. script.sh > /dev/null

どのように解決するのですか?

の「シェル組み込みコマンド」の項によると、以下のようになります。 bash manpage , . 別名 source は、ソースとなるスクリプトに渡される引数のリストをオプションで取ります。それを使って、何もしないオプションを導入することができます。例えば script.sh はそうなる可能性があります。

#!/bin/sh

foo() {
    echo foo $1
}

main() {
    foo 1
    foo 2
}

if [ "${1}" != "--source-only" ]; then
    main "${@}"
fi

unit.sh はあり得る。

#!/bin/bash

. ./script.sh --source-only

foo 3

次に script.sh は正常に動作し unit.sh のすべての関数にアクセスできるようになります。 script.sh のすべての関数にアクセスできますが main() のコードは呼び出されません。

への余分な引数があることに注意してください。 source は POSIX には存在しないので /bin/sh はそれを扱わないかもしれません。 #!/bin/bash の冒頭にある unit.sh .