web-dev-qa-db-ja.com

Bashスクリプトの予期しない動作:最初に関数を実行し、その後エイリアスを実行します

次のスクリプトを実行すると

#!/usr/bin/env bash

main() {
    shopt -s expand_aliases 
    alias Hi='echo "Hi from alias"'
    Hi  # Should Execute the alias
    \Hi # Should Execute the function
    "Hi"
}

function Hi() {
    echo "Hi from function"
}
main "$@"

初めて関数を実行し、その後常にエイリアスとして実行します。

$ . Sample.sh
Hi from function
Hi from function
Hi from function
$ . Sample.sh
Hi from alias
Hi from function
Hi from function

なぜですか?


これは、次の場合には発生しません

#!/usr/bin/env bash

function Hi() {
    echo "Hi from function"
}

shopt -s expand_aliases 
alias Hi='echo "Hi from alias"'
Hi  # Should Execute the alias
\Hi # Should Execute the function
"Hi"

初めて関数を実行し、その後常にエイリアスとして実行します。

$ . Sample.sh
Hi from alias
Hi from function
Hi from function
$ . Sample.sh
Hi from alias
Hi from function
Hi from function
5
Nikhil

関数のエイリアス展開は、関数が実行されるときではなく、関数が読み取られるときに行われます。関数のエイリアス定義は、関数の実行時に実行されます。

エイリアスと関数 を参照してください
および https://www.gnu.org/software/bash/manual/html_node/Aliases.html

つまり、関数mainが実行されたときにエイリアスが定義されますが、関数が初めて読み取られたときは、エイリアスはまだ定義されていません。したがって、初めて関数mainは関数Hiを3回実行します。

スクリプトを2回目にソースするとき、エイリアスは前回の実行からすでに定義されており、関数定義が読み取られるときに展開できます。関数を呼び出すと、エイリアスが展開されて実行されます。

異なる動作は、スクリプトが. Sample.shで提供されている場合、つまり同じシェルで複数回実行されている場合にのみ発生します。別のシェルで./Sample.shとして実行すると、常に最初の実行の動作が表示されます。

10
Bodo