陈斌彬的技术博客

Stay foolish,stay hungry

Mac-shell 变量,数据重定向和管道

img

变量

变量的作用

变量与其他程序设计语言一样,都是存储数据,然后被程序引用。相比于不使用变量,而是直接使用数据,存在两个问题:

1.当数据改变时,直接使用数据的时候却不能灵活地根据数据改变而随着改变,而使用变量却不同,它能够做到这点。

2.当数据发生变化时,如果想保证数据一致性,必须查找所有引用该数据的所有地方,然后将它修改,当下一次再需要修改时,也是像这种情况一样,是多么繁琐的事,而变量却不用,只需要修改变量值即可。

因此,变量具有可变性易于修改的两个特点。

变量的分类

shell 中,大概分为两种变量:环境变量局部变量,主要区别在于它们的使用范围不同,环境变量可以在父进程与子进程之间共享,而自定义变量只在本进程使用。举一个简单的例子来说明:

img

首先设置一个 shell 变量 devname=John,然后输入 bash 打开一个新的 shell ,而这个 shell 是子进程,然后 echo $devname 输出变量值,变量值为空,最后 exit 退出子进程。

但使用 export devname 设置环境变量后,再次进入输入 bash 进入子进程之后,echo $devname 输出变量值,这次变量值是 John

img

查看环境变量 envset

如果想查看系统中以及自定义有哪些环境变量,可以使用 env 命令:

img

set 命令不仅能查看环境变量,还可以查看与 shell 接口有关的变量

img

变量操作

1.显示 echo $variable

如果你想显示某个变量的值,例如 PATH,你只需要输入:

echo $PATH

img

注意:需要在变量名前加上一个符号 $,这样才能访问变量

2.设置 variable=value 和取消 unset

如果你想设置某个变量的值,只需在变量名和变量值之间用符号 = 连接就行了,例如:

img

由上面的输入命令 echo $devname,显示结果为空。由此可知,一开始如果没有设置某个变量时,它的是为空。另外,设置变量的规则还需要几点注意:

1.在命名变量名时,变量名称只能是英文字母和数字,而且首字母不能是数字

img

2.等号 = 两边不能有空格

img

3.如果变量值有空格,可用双引号 " " 或单引号 ' ' 来包围变量值,但两者是有区别: 双引号 " " 内的一些特殊字符,可以保持原有的特性,例如:

img

而单引号 ' ' 内的一些特殊字符,仅为一般字符,即纯文本,例如:

img

4.如果想显示一些特殊字符($、空格、!等),在字符前面加上用转义字符 \

5.有些时候,变量的值可能来源于一些命令,这时你可以使用反单引号命令或$(命令),例如: 使用反单引号命令的方式

img

使用 $ 命令:

img

6.如果变量需要在其他子进程使用,用 export 关键字来设置变量为环境变量

7.系统环境变量一般都是字母全部大写,例如:PATHHOMESHELL

8.如果想取消设置变量的值,使用 unset variable 命令。注意,变量之前是没有符号 $

img

环境配置文件

之前那些设置的环境变量,一旦退出系统后,就不能再次使用,如果想再次使用,必须重新再设置才行。如果想就算退出系统,也能重新使用自定义的环境变量,那怎么办呢?

不用怕,系统提供一些环境配置文件:/etc/profile~/.bash_profile/etc/profile 是系统整体的设置,每个用户共享,最好不要修改;而 ~/.bash_profile 属于单个用户的设置,每个用户设置后,互不影响和共享。但因为我使用 oh my zsh ,之前~/.bash_profile 设置一些配置都不生效了,但它提供一个环境配置文件 .zshrc,所以如果想设置环境变量 TEST,只需将 export TEST=test 添加 .zshrc 即可。

img

但在 .zshrc 文件设置好环境变量 TEST 后,echo $TEST 为空,原因是还没使用 source 命令来读取环境配置文件。使用source .zshrc 命令之后,设置环境变量 TEST生效了。

img

数据重定向

含义

当输入命令行时,一般都有输入参数(standard input),而命令行处理完之后,一般都有输出结果,结果有可能成功(standard output),也有可能失败(standard error),而这些结果一般都会输出到屏幕上,如果你想控制结果输出到文件或以文件作为输入的话,你需要了解数据重定向的分类和符号操作。

img

分类

数据重定向主要分为三类:

  • stdin,表示标准输入,代码为 0,使用 <<< 操作符

符号 < 表示以文件内容作为输入

符号 << 表示输入时的结束符号

  • stdout,表示标准输出,代码为 1,使用 >>> 操作符

符号 > 表示以覆盖的方式将正确的数据输出到指定文件中

符号 >> 表示以追加的方式将正确的数据输出到指定文件中

  • stderr,表示标准错误输出,代码为 2,使用 2>2>> 操作符

符号 2> 表示以覆盖的方式将错误的数据输出到指定文件中

符号 2>> 表示以追加的方式将错误的数据输出到指定文件中

使用

stdout

当你输入 ls 命令,屏幕会显示当前目录有哪些文件和目录;而当你使用符号 > 时,输出结果将重定向到 dir.txt 文件,而不显示在屏幕上

img

而符号 > 与符号 >> 有什么区别呢? > 表示当文件存在时,将文件内容清空,然后 stdout 结果存放到文件中。而 >> 表示当文件存在时,文件内容并没有清空,而是将 stdout 结果追加到文件尾部。

当你再次输入命令 ls > dir.txt 时,文件内容并没有改变,因为之前文件内容被清空,然后 stdout 结果存放在 dir.txt 文件.

img

而你这次使用符号 ls >> dir.txt 的话,文件内容被追加到 dir.txt 文件

img

stderr 这次我输入命令 ls test 显示一个不存在的文件,会显示错误信息。然后将错误信息输出到文件 error.txt

img

如果你想追加错误信息,可以使用 2>> 符号

img

stdout & stderr

  • stdoutstderr 分离: >2> 符号 输入 ls README.md test,在屏幕显示既有正确信息,也有错误信息,如果想将正确信息和错误信息分离到不同文件,你可以同时使用 >2> 符号。

img

  • stdoutstderr 合并:&> 符号 如果你想将正确信息和错误信息合并,且输出到同一个文件,可以使用 &> 符号

img

stdin

一般输入一些简单的数据的方式都是通过键盘,但是如果要输入大量的数据,最好还是通过文件的方式。举一个简单例子: 首先输入 cat > test 命令之后,你就可以输入内容,然后键入回车,最后在键盘上按下 Ctrl+D (或者键入Control-D)保存退出。 那些内容最终会存放在 test 文件。

img

但如果有大量数据从一个文件导入到 test 文件时,此时需要用到 < 符号

img

还一个符号 << 需要解释,符号 << 表示输入时的结束符号。输入 cat > test << "eof" 命令之后,你就可以输入内容,那些内容最终会存放在 test 文件,输入完内容后可以输入 eof 来结束输入。

img

管道

在 Unix 设计哲学中,有一个重要设计原则–KISS(Keep it Simple, Stupid),大概意思就是只关注如何做好一件事,并把它做到极致。每个程序都有各自的功能,那么有没有一样东西将不同功能的程序互相连通,自由组合成更为强大的宏工具呢?此时,管道出现了,它能够让程序实现了高内聚,低耦合

img

如果我想查看文件是否存在某个关键字,此时我可以使用管道:

img

命令 cat LICENSE | grep 'It'的处理过程分为两步:

1.cat LICENSE 查看文件内容

2.然后将 cat LICENSE 输出的内容作为 grep 'It' 命令的输入,再进行处理。

上面一个很关键的符号 |,就是管道,它能够将前一个命令处理完的 stdout 作为下一条命令 stdin