【发布时间】:2009-12-11 04:58:38
【问题描述】:
请告诉我如何在父 shell(bash、sh 或 ksh)中导出函数,以便从父进程启动的所有子进程都可以使用该函数?
【问题讨论】:
请告诉我如何在父 shell(bash、sh 或 ksh)中导出函数,以便从父进程启动的所有子进程都可以使用该函数?
【问题讨论】:
export -f 功能是 Bash 特有的:
父母
#!/bin/bash
plus1 () { echo $(($1 + 1)); }
echo $(plus1 8)
export -f plus1
./child 14 21
孩子
#!/bin/bash
echo $(plus1 $(($1 * $2)) )
【讨论】:
在sh 中,不可能导出函数,如noted by Charles Duffy。
【讨论】:
函数本质上是不可导出的。不过你可以导出字符串,所以我这里有个小技巧:
func="$(typeset -f funcname)"
export func
要导入函数,请从导出的字符串中重新定义它:
# in subshell
eval "$func"
【讨论】:
eval的标准警告:unix.stackexchange.com/a/278439/109669
如果您使用的是 ksh 或 zsh:
您可以使用环境变量FPATH,您可以在其中放置所有函数。
如果在交互式解释器上设置了FPATH,并且在当前shell 环境或PATH 中找不到命令或函数,则会搜索列出的目录中是否存在以缺少的命令命名的文件.如果找到了,则它是在当前 shell 环境中获取的,并期望定义函数。
因此,您可以将所有函数放在FPATH 中的某个位置,子脚本也可以找到它。
您可以在 shell 脚本中使用autoload 命令来加载您需要的功能:
autoload fun_a fun_b
在 zsh 中,FPATH 工作需要autoload。 在ksh 及其近亲中,我相信它只会导致FPATH 中定义的函数覆盖常规命令您的 PATH,就像直接定义一样。
关于FPATH和autoload的一些细节:
【讨论】:
如果您使用( ) 创建子shell,那么它们将继承所有定义、参数和shell 变量的快照。
如果你像程序一样执行它们,那么你可以把定义放在.bashrc。
如果您试图欺骗现有脚本执行包装器或替换 PATH 命令,则 .bashrc 将根据执行的详细信息起作用。如果没有,您可以改为执行一个包装脚本,该脚本只需执行定义函数的包含文件的 . 或 source,然后使用要替换的命令对 shell 脚本执行相同的操作。
包装脚本可能类似于:
script=$1
shift
. include.sh
. $script "$@"
想法是第一个参数是真实脚本的名称,其余参数是args,然后运行上面的脚本。
【讨论】:
declare -x -f NAME
更多信息
-f 将操作或显示限制为函数名称和定义 -x 使名称导出【讨论】:
bash。 (ksh 对应于 declare,typeset,有一个 -x 选项,但它仅适用于 变量,不适用于函数;zsh 同上)。