上文中曾说到:

  • 所谓的环境变量的真实面目其实就是个任意字符串
  • 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. 从人类社会的角度看OO(独家视角)

    引言 在OO的工作中,我们一定会涉及到类,抽象类和接口.那么类和抽象类以及接口到底扮演的什么角色? 本文主要是从人类社会的角度阐述类与抽象类以及接口的"社会"关系,从而让我们抛弃书 ...

  2. POJ1151Atlantis 矩形面积并[线段树 离散化 扫描线]

    Atlantis Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 21734   Accepted: 8179 Descrip ...

  3. django博客功能实现——标签功能

    标签功能添加流程 0.功能概括 标签作为文章中的分类标记,会显示出该文章是关于哪一方面的文章,比如是关于python的还是关于django的. 当我们点击该标签的时候,会出现该博客中所有属于该标签的文 ...

  4. [No00007E]2016-面经[中]

    目录: 写一份动人简历的九个步奏 英文简历必备的十大元素 写一份动人简历的九个步骤 写一份动人的简历可以算得上是找工作最难的部分之一,但是,通过下面九步,这件事不再那么难了. 简历定位.雇主们之所以花 ...

  5. 将对象转化成json字符串

    public static String getObjectString(Object object){ String ObjectString = null; try { ObjectMapper ...

  6. IIS7.5使用web.config设置伪静态的二种方法(转)

    近几天公司里开发的项目有几个运行在IIS7.5上,由于全站采用的是伪静态,因此从网上找到两两种方法来实现.这两种方法各有优势:第一种比较灵活,只要把文件拷到根目录下,即可直接显示所有伪静态页面(适用于 ...

  7. Linux Linux程序练习十八

    题目:编写一个TCP服务器和客户端,基于TCP的并发远程shell 要求实现: )对于所有收到的客户端消息,作为命令行进行执行, 并且将命令行的输出结果返回给客户端 )要求使用并发结构 )实现关键代码 ...

  8. Android ORM 框架之 greenDAO 使用心得

    前言 我相信,在平时的开发过程中,大家一定会或多或少地接触到 SQLite.然而在使用它时,我们往往需要做许多额外的工作,像编写 SQL 语句与解析查询结果等.所以,适用于 Android 的ORM  ...

  9. Django 1.9 Post 时候出现 CSRF token missing or incorrect 错误

    get 的时候没有问题,只有在post的时候出现出现这个错误 在方法中加入 @csrf_exempt

  10. 开发haproxy管理平台

    1.说明:该脚本仅适用于Linux操作系统2.使用方法: 在该脚本同级目录下要创建一个名字叫做 haproxy 的文件 haproxy 文件内容如下 global log 127.0.0.1 loca ...