SHELL脚本攻略(读书笔记)--1.11 命令替换和子shell的作用
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SHELL脚本攻略(读书笔记)--1.11 命令替换和子shell的作用相关的知识,希望对你有一定的参考价值。
1.11.1 命令替换
Linux中使用反引号“``”(在波浪线的按键上)或者$()来执行命令替换。一般以$()更直观也更方便敲入。
[[email protected] tmp]# echo Can you tell me what date it is? Oh my pleasure $(date +%F)
Can you tell me what date it is? Oh my pleasure 2016-09-25
[[email protected] tmp]# echo Can you tell me what date it is? Oh my pleasure `date +%F` ?或者使用反引号
使用$()可以让括号里的命令提前于整个命令运行,然后作为stdin交给整个命令。它可以存在于任何地方。
实际上它的本质是通过()开启了一个子shell,在子shell里运行括号里的命令,运行完退出子shell,然后父shell将结果通过$符号打包,因为这个结果经常交给外部命令,所以不能让结果有换行的行为,所以打包过程中默认将换行符替换为了空格,当然对于只有一行的结果就无所谓了。
下面这个例子展示的就是多行的,可以看到在$打包()的时候去掉了换行符,变为了空格,除了最后一个。
[[email protected] tmp]# (cat abc.sh) | cat -E
#!/bin/bash$
#文件名:abc.sh$
printf "%-s\\t %-s\\t %s\\n" No Name Mark$
printf "%-s\\t %-s\\t %4.2f\\n" 1 Sarath 80.34$
printf "%-s\\t %-s\\t %4.2f\\n" 2 James 90.998$
printf "%-s\\t %-s\\t %4.2f\\n" 3 Jeff 77.564$
[[email protected] tmp]# echo $(cat abc.sh) | cat -E
#!/bin/bash #文件名:abc.sh printf "%-s\\t %-s\\t %s\\n" No Name Mark printf "%-s\\t %-s\\t %4.2f\\n" 1 Sarath 80.34 printf "%-s\\t %-s\\t %4.2f\\n" 2 James 90.998 printf "%-s\\t %-s\\t %4.2f\\n" 3 Jeff 77.564$
使用双引号引用可以保留换行符。
[[email protected] tmp]# echo "$str"
#!/bin/bash
#文件名:abc.sh
printf "%-s\\t %-s\\t %s\\n" No Name Mark
printf "%-s\\t %-s\\t %4.2f\\n" 1 Sarath 80.34
printf "%-s\\t %-s\\t %4.2f\\n" 2 James 90.998
printf "%-s\\t %-s\\t %4.2f\\n" 3 Jeff 77.564
下面的命令确实可以知道括号是开启了子shell的。
[[email protected] tmp]# ps -ef|grep bash;(ps -ef|grep bash);ps -ef|grep bash
root 6557 6554 0 08:41 pts/1 00:00:02 -bash
root 7925 6557 0 15:44 pts/1 00:00:00 grep --color=auto bash
root 6557 6554 0 08:41 pts/1 00:00:02 -bash
root 7926 6557 0 15:44 pts/1 00:00:00 -bash ?子shell
root 7928 7926 0 15:44 pts/1 00:00:00 grep --color=auto bash
root 6557 6554 0 08:41 pts/1 00:00:02 -bash
root 7930 6557 0 15:44 pts/1 00:00:00 grep --color=auto bash
1.11.2 关于子shell
子shell会继承父shell的环境变量以及一些其他的变量,但是还有一些是不继承的。在BASH 4以后可以使用$BASH_SUBSHELL变量来查看从当前进程开始的子shell层数。
1.11.3 何时产生子shell
1. 运行脚本
当运行脚本里有#!/bin/bash在第一行,就使用这个/bin/bash开启了一个子shell,当然也可以是其他bash。脚本运行完毕回到父shell,所以脚本不会对父shell产生任何环境上的改变。
2. 使用括号()
在()里运行命令也会开启了一个子shell。因此在Linux中不要随便乱写()来想着改变优先级,除非将其转义,并且转以后的括号要与括号里的内容之间有空格。
[[email protected] tmp]# echo $BASH_SUBSHELL
0
[[email protected] tmp]# (echo $BASH_SUBSHELL)
1 ?说明开启了一层子shell
但是请看下面的例子。
[[email protected] tmp]# abc=123
[[email protected] tmp]# (echo $abc)
123
本应该不继承自定义的变量,但是结果却得到了父shell的结果。这是因为fork一个新的进程会使用父进程的值赋值。所以()这样的操作符打开的子shell会得到父shell的值,但是使用脚本就不能得到了。
fork进程:UNIX关于进程管理的一个术语,本质是新开一个进程,但是不是从磁盘加载代码,而是从内存现有进程复制一份。
3. 使用显式的bash
实际上执行脚本就是运行了bash进入子shell,这样的进入方式不会使用父进程的值来赋值。
[[email protected] tmp]# bash
[[email protected] tmp]# echo $BASH_SUBSHELL
0 ?为0,因为现在$BASH_SUBSHELL以子shell作为计算的父shell了
以上是关于SHELL脚本攻略(读书笔记)--1.11 命令替换和子shell的作用的主要内容,如果未能解决你的问题,请参考以下文章
SHELL脚本攻略(学习笔记)--1.3 多命令逻辑执行顺序