上文中曾说到:

  • 所谓的环境变量的真实面目其实就是个任意字符串
  • 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函数 }

Bash 是如何从环境变量中导入函数的的更多相关文章

  1. ***LINUX添加PHP环境变量:CentOS下将php和mysql命令加入到环境变量中

    CentOS系统下如何将PHP和mysql命令加入到环境变量中,在Linux CentOS系统上 安装完php和MySQL后,为了使用方便,需要将php和mysql命令加到系统命令中,如果在没有添加到 ...

  2. 将python文件加入到python的环境变量中

    在python中,把一个python文件加入到python环境变量中,以方便其他python文件调用.有两种方式,下面对其进行简单的介绍 方式一: 导入系统自带的sys模块,然后将文件的路径进行追加或 ...

  3. 将NuGet配置到环境变量中

    https://docs.nuget.org/consume/command-line-reference Installing The NuGet command line may be insta ...

  4. linux系统下将php和mysql命令加入到环境变量中的方法

    在Linux CentOS系统上安装完php和MySQL后,为了使用方便,需要将php和mysql命令加到系统命令中,如果在没有添加到环境变量之前,执行 “php -v”命令查看当前php版本信息时时 ...

  5. linux CentOS 系统下如何将php和mysql命令加入到环境变量中

    在Linux CentOS系统上安装完php和MySQL后,为了使用方便,需要将php和mysql命令加到系统命令中,如果在没有添加到环境变量之前,执行“php -v”命令查看当前php版本信息时时, ...

  6. python解释器的安装;python2与python3同时在环境变量中时的解决方案

    新文档 html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,addres ...

  7. CentOS下将php和mysql命令加入到环境变量中的几种方法

    Linux CentOS配置LAPM环境时,为了方便,将php和mysql命令加到系统环境命令,下面我们记录几种在linux下将php和mysql加入到环境变量中的方法. 如果在没有添加到环境变量之前 ...

  8. Anaconda下的python如何写入环境变量中

    Anaconda是一个非常好的python管理软件,实际使用起来要比直接用python自带的管理工具更好. 若需要将Anaconda下的python.exe添入环境变量中,需要如下设置 如上图所示,需 ...

  9. 【转】Linux将composer的bin目录放到PATH环境变量中

    将composer的bin目录放到PATH环境变量中 使用composer global config bin-dir --absolute查看composer的bin目录 输出类似 Changed ...

随机推荐

  1. nginx $document_uri 防止死循环

    $document_uri 表示访问的url 现在我的需求是,访问 www.xxx.com 请求到 www.xxx.com/bbs/ 在nginx配置文件中加入 if ($document_uri ! ...

  2. Android APP 两种用程序拨号的方式

    想在APP中添加一个拨号功能该怎样做呢?Android提供了两种方式,一种是ACTION_CALL方式直接拨打,另一种是ACTION_DIAL方式打开系统的拨号界面. 下面我们来做个小例子 首先需要在 ...

  3. 前端构建工具gulp使用

    前端自动化流程工具,用来合并文件,压缩等. Gulp官网 http://gulpjs.com/ Gulp中文网 http://www.gulpjs.com.cn/ Gulp中文文档 https://g ...

  4. postman使用之二:数据同步和创建测试集

    数据同步 启动postman 后在右上角可以登录账号,登录后就可以同步自己的api测试脚本,连上网在办公区在家都可以同步. 创建测试集 1.点击collections,点击add folder 2.c ...

  5. python有超时的windows系统时间设置代码

    手边的笔记本用久了,cmos电池可能又没电了.每次开机时间都不对,导致访问一些有https的网页会出现警告信息. 于是找了找通过python脚本设置系统时间的方法,发现了两种,其一是调用socket直 ...

  6. jquery的add()用法总结

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="utf-8&quo ...

  7. iOS逆向工程资料

    链接: 基于iOS逆向工程的微信机器人 - 猫友会大讲坛第1期 我的失败与伟大 —— 创业必备的素质(狗神经验谈)

  8. 文件夹右键添加“DOS”命令

    导入注册表 Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\Folder\shell\RunCMD] @="进入命令行&quo ...

  9. 豪斯课堂K先生全套教程淘宝设计美工第一期+第四期教程(无水印)

    第一期课程包括 <配色如此简单> <配色的流程><对称之美>第二期课程包括 <字体的气质及组合><平衡及构图形式><信息的筛选与图片的 ...

  10. Swift学习(一):自定义运算符 operator

    自定义运算符仅能包含这些字符: / = - + * % < >!& | ^.~ 运算符位置: 前置运算符 prefix 中间运算符 infix 后置运算符 postfix 运算符其 ...