Bash 是如何从环境变量中导入函数的

上文中曾说到:

  • 所谓的环境变量的真实面目其实就是个任意字符串
  • Bash 在启动时会将 environ 数组中包含 = 号的字符串导入成为自己的变量
  • Bash 在启动外部命令时会将自己内部标记为环境变量的变量重组成字符串数组赋值给 environ

本文中继续深入讲三点:

  • environ 数组中可能存在 = 左边名字相同的元素,也就是同名的环境变量,Bash 是怎么导入的?
  • Bash 还可以从环境变量中导入函数,甚至同时导入两个同名的变量和函数
  • Bash 还可以同时导出两个同名的变量和函数

如果有两个同名的环境变量,很简单,那么后面的值会覆盖前面的:

env foo=1 foo=2 bash -c 'echo $foo'

2

上篇文章中我们没有提到过函数,Bash 其实是可以从环境变量中导入函数的,比如下面这样:

foo() { echo foo函数; }

export -f foo

bash

foo

foo函数

上一级的 Shell 把函数传给了它的 child shell,Bash 是怎么实现的呢?我们用 env 命令演示一下:

 env 'BASH_FUNC_foo%%=() { echo foo函数; }' bash -c 'foo'

foo函数

其实 Bash 就是把满足 "BASH_FUNC_函数名%%=(){ 函数体" 格式的环境变量作为函数源码解析并导入。所以两个同名的变量和函数并不会冲突,可以同时导入,像这样:

 env 'foo=1' 'BASH_FUNC_foo%%=() { echo $1; }' bash -c 'foo $foo'

1

既然可以同时导入,那么导出更没问题了:

foo=1

foo(){ echo foo函数; }

export foo;export -f foo

env

...

foo=1

BASH_FUNC_foo%%=() { echo foo函数

}

...

Bash 4.3.30 之前的版本

注意,本文所讲的表现仅适用于 Bash 4.3.30 及之后的版本,之前的 Bash 版本在导出函数时不会给函数名加上 BASH_FUNC_ 前缀和 %% 后缀,在导入时也不会识别前缀后缀,只要看到 = 右边是 "() {" 这四个字符,就按函数导入,像这样:

env 'foo=() { echo foo函数; }' bash -c 'foo'

foo函数

由于环境变量字符串的转换和识别规则不同,假如你在 Bash 4.3.30 中打开一个 Bash 3.2.25,后者是无法继承到前者导出的函数的:

bash4.3.30

foo() { echo foo函数 ; }

export -f foo

bash3.2.25

foo

bash3.2.25: foo: command not found

反之亦然,同时 foo 会被导入成一个变量:

bash3.2.25

foo() { echo foo函数 ; }

export -f foo

bash4.3.30

foo

bash3.2.25: foo: command not found

echo $foo

() { echo foo函数 }

posted @   紫云飞  阅读(1675)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2012-09-22 [译]JavaScript:Array.prototype和[]的性能差异
2012-09-22 [译]JavaScript:用什么来缩进
2012-09-22 [译]JavaScript:什么时候能用==
点击右上角即可分享
微信分享提示