bash/zsh 中的元编程以重新加载 shell 脚本

meta programming in bash/zsh to reload shell script

我有三个zsh脚本,

meta_zsh.sh,

# meta_zsh.sh
meta_s() {
    eval 'echo "${(%):-%x} re-define s()"; s() { echo " calling s() ${(%):-%x}"; }'
}

script_zsh.shscript_zsh_2.sh(内容相同)

# script_zsh.sh and script_zsh_2.sh (the same content)
meta_s
s

在 zsh 中执行以下命令

$ . ./meta_zsh.sh; . ./script_zsh.sh; . ./script_zsh_2.sh

产出

./meta_zsh.sh re-define s()
  calling s() ./script_zsh.sh
./meta_zsh.sh re-define s()
  calling s() ./script_zsh_2.sh

问题是,如何在bash中实现同样的效果?

我尝试将 ${(%):-%x} 更改为 ${BASH_SOURCE[0]}[=21=],但均无效。

何必呢?

在以上 meta_xx.sh 来源之后 ~/.zshrc (~/.bashrc),

我可以在 shell 中输入 s 来重新加载最近的源脚本, 如果 meta_s 在其中。

BASH_SOURCE实际上是调用者的堆栈,${BASH_SOURCE[0]}是当前文件,所以你可以使用${BASH_SOURCE[1]}:

$ cat meta.sh 
meta_s() {
    eval 'CALLER=${BASH_SOURCE[1]}; echo "$CALLER re-define s()"; s() { echo " calling s() $CALLER"; }'
}
$ cat s1.sh 
meta_s
s
$ cat s2.sh 
meta_s
s
$ . meta.sh ; . s1.sh ; . s2.sh 
s1.sh re-define s()
 calling s() s1.sh
s2.sh re-define s()
 calling s() s2.sh