私が読んでいるBourneシェル用に作成されたMavenラッパーのソースコード。私は次の内容を見つけました。
if [ -z "$JAVA_HOME" ]; then
javaExecutable="$(which javac)"
if [ -n "$javaExecutable" ] && ! [ "$(expr "$javaExecutable" : '\([^ ]*\)')" = "no" ]; then
# snip
expr
arg1
andと一緒に使用すると、arg2
aは正規表現と一致します:
。通常、結果は一致する文字の数です。たとえば、次のようになります。arg1
arg2
$ expr foobar : foo
3
ただし、キャプチャ括弧(\(
および\)
)を使用すると、最初のキャプチャ括弧の内容が返されます。
$ expr foobar : '\(foo\)'
foo
今まではそんなに良くなった。
上記で引用したソースの式を自分のコンピュータで評価すると、次のような結果が得られます。
$ javaExecutable=$(which javac)
$ expr "$javaExecutable" : '\([^ ]*\)'
/usr/bin/javac
存在しない実行可能ファイルの場合:
$ nonExistingExecutable=$(which sjdkfjkdsjfs)
$ expr "$nonExistingExecutable" : '\([^ ]*\)'
つまり、存在しない実行可能ファイルの場合、出力は改行を含む空の文字列です。
which javac
ソースコードで私を混乱させるのは、arg1
(to)の出力がexpr
文字列を返す方法ですno
。
which
何も返しませんが、実行可能ファイルが見つからないときに返すバージョンはありますか?no
そうでなければ、このステートメントは常に真と評価され、これは奇妙です。
答え1
伝統的にエラーメッセージを印刷して成功ステータスを返すwhich
cshスクリプト。no foo in /usr/bin:/bin
(少なくとも1つの共通バージョンがあり、動作が異なるバージョンがある可能性があります。)はいFreeBSD 1.0で起動(はい、それは古代です):
if ( ! $?found ) then
echo no $arg in $path
endif
(この古典的な実装は、ユーザーのロードにも悪名高いです.cshrc
。これは変更され、PATH
誤った出力を引き起こす可能性があります。)
最新のシステムは、一般的にCまたはshで書かれたさまざまな実装を持ち、which
エラー条件処理の最新の標準に従います。つまり、stdoutに出力されず、終了状態が0ではありません。
答え2
技術的には、これは次の点を確認するチェックです。最初の単語(または空白以外の文字の最初のシーケンス)を出力します。そして、いくつかのwhich
実装は沈黙しません。
zsh
which foo
標準foo not found
出力に書き込む- GNUはstderr
which foo
に書き込みます。which: no foo in (<contents of $PATH>)
- テストする項目はありませんが、以前のUnixのマンページには、「引数名を持つ実行可能ファイルがパスに見つからない場合は診断情報を印刷します」というフレーズがあります。標準エラー)。
印刷物で始まる特定のバリエーションが何であるかはわかりませんが、no
GNUはwhich
このバリエーションからインスピレーションを受けたかインスピレーションを受けた可能性があります。