首先,Shell 是一个程序,提供一个与用户对话的环境。这个环境只有一个命令提示符,让用户从键盘输入命令,所以又称为命令行环境(command line interface,简写为 CLI)。Shell 接收到用户输入的命令,将命令送入操作系统执行,并将结果返回给用户。本书中,除非特别指明,Shell 指的就是命令行环境。
其次,Shell 是一个命令解释器,解释用户输入的命令。它支持变量、条件判断、循环操作等语法,所以用户可以用 Shell 命令写出各种小程序,又称为脚本(script)。这些脚本都通过 Shell 的解释执行,而不通过编译。
最后,Shell 是一个工具箱,提供了各种小工具,供用户方便地使用操作系统的功能。
历史上,主要的shell有很多种比如sh、Bash、csh、zsh、tcsh等等,这个会根据不同的linux发行版就有不同的终端程序。
然后再解释两个概念:父Shell和子Shell。
在Bash的环境中,是可以调用新的Bash比如:
[root@omp-test-201-93 ~]# ps aux|grep bash
root 9597 0.0 0.0 115676 2076 pts/0 Ss 14:11 0:00 -bash
root 9807 0.0 0.0 112812 944 pts/0 S+ 14:13 0:00 grep --color=auto bash
[root@omp-test-201-93 ~]# bash
[root@omp-test-201-93 ~]# ps aux|grep bash
root 9597 0.0 0.0 115676 2076 pts/0 Ss 14:11 0:00 -bash
root 9817 0.2 0.0 115676 2056 pts/0 S 14:13 0:00 bash
root 9838 0.0 0.0 112812 948 pts/0 S+ 14:13 0:00 grep --color=auto bash
[root@omp-test-201-93 ~]# echo $$
9817
[root@omp-test-201-93 ~]# (echo $BASHPID)
9857
[root@omp-test-201-93 ~]# { echo $BASHPID; }
9817
我们所有的命令都是通过ssh远程连接的,登录成功后,ssh中就生成了第一个bash,上述又重新执行了bash,就会产生第二个bash,通过ps可以查询到,然后这第二个bash就是子Shell。
也可以通过pstree来查看我们的执行环境
Ok. 言归正传,铺垫的差不多了,进入第一个主题:
单小括号()与花括号{}的区别一:
()执行命令或者命令串时,会重新开启新的子shell来顺序执行,{}则是直接在当前Shell中执行。
所以在工作中若使用小括号,那么在其中执行的命令的修改只在子Shell中生效,命令结束就会回到父Shell中,修改随机丢失;如果是花括号,自然就不会丢失,命令结束,修改依然存在
单小括号()与花括号{}的区别二:
小括号和花括号都可以执行多条命令可以用";"分隔,但是花括号的第一个命令与左括号之间要有一个空格,同时";"结尾;小括号就没那么多规矩不需要空格,不需要";"结尾。
看例子:
[root@omp-test-201-93 ~]# { echo $BASHPID }
> ^C
[root@omp-test-201-93 ~]# {echo $BASHPID}
bash: {echo: command not found
[root@omp-test-201-93 ~]# { echo $BASHPID; }
9817
[root@omp-test-201-93 ~]# (echo 1;echo $BASHPID)
1
10094
[root@omp-test-201-93 ~]# { echo $BASHPID;}
9817
说完区别,单刷一下两种括号常见的独立使用场景
一、单小括号()使用场景
1.1 命令替换
等同于`command`。即shell脚本中存在$()结构的代码,shell会先执行该结构代码得到标准输出,并放到原来的命令中。(tcsh不支持该功能)
1.2 初始化数组
array=(a b c d)
二、花括号使用场景:
2.1 变量调用、赋值
${file} 等同于$file,但是前者会更精准取到变量的内容
[root@tomp-test-201-93est ~]# t="a/b/c"
[root@omp-test-201-93 ~]# echo $t.txt
a/b/c.txt
[root@omp-test-201-93 ~]# echo ${t}ommand.txt
a/b/command.txt
[root@omp-test-201-93 ~]# echo $tommand.txt
.txt
${file=filename.txt}、${file:=filename.txt}、${file-filename.txt}等等 这种用于来解决null或未赋值的情况
[root@omp-test-201-93 ~]# (testfile=1;echo ${testfile-test.txt})
1
[root@omp-test-201-93 ~]# (testfile=1;echo ${testfile:-test.txt})
1
[root@omp-test-201-93 ~]# (testfile=1;echo ${testfile+test.txt})
test.txt
[root@omp-test-201-93 ~]# (testfile=1;echo ${testfile:+test.txt})
test.txt
[root@omp-test-201-93 ~]# (testfile=1;echo ${testfile=test.txt})
1
[root@omp-test-201-93 ~]# (testfile=1;echo ${testfile:=test.txt})
1
[root@omp-test-201-93 ~]# (testfile=1;echo ${testfile?test.txt})
1
[root@omp-test-201-93 ~]# (testfile=1;echo ${testfile:?test.txt})
1
[root@omp-test-201-93 ~]# (testfile="";echo ${testfile-test.txt})
[root@omp-test-201-93 ~]# (testfile="";echo ${testfile:-test.txt})
test.txt
[root@omp-test-201-93 ~]# (testfile="";echo ${testfile+test.txt})
test.txt
[root@omp-test-201-93 ~]# (testfile="";echo ${testfile:+test.txt})
[root@omp-test-201-93 ~]# (testfile="";echo ${testfile=test.txt})
[root@omp-test-201-93 ~]# (testfile="";echo ${testfile:=test.txt})
test.txt
[root@omp-test-201-93 ~]# (testfile="";echo ${testfile?test.txt})
[root@omp-test-201-93 ~]# (testfile="";echo ${testfile:?test.txt})
bash: testfile: test.txt
[root@omp-test-201-93 ~]# (testfile="";echo ${testfile:=test.txt};echo $testfile)
test.txt
test.txt
[root@omp-test-201-93 ~]# (testfile="";echo ${testfile:-test.txt};echo $testfile)
test.txt
来个总结:
重点区分unset、null 和非空三种状态。
":-" 、":="、":?" 当$testfile没有设定或者为空时,file会被赋值test.txt。但是":-" 、":=" 仍然有不同之处,:=替换${testfile:=test.txt}的同时,还会给testfile赋新值。(这两种都是比较常用的,用于我们在写脚本时可能变量忘记声明或者获取错误结果导致空值的情况。可以直接给个默认值。比如获取一个微信预警的token,网络问题导致token获取失败,时间比对出问题就会导致下游的脚本结果出错,要避免此种情况起码要多写五六行if..else)。特殊的":?" 会将test.txt输出到STDERR,结束脚本;
恰恰相反的":+" 则是当file有值的时候file会重新赋值test.txt;
"-"、"="、"?" 当$testfile没设定时testfile会被赋值test.txt;相反的+ 空值和非空值才会给赋值,这种情况倒是比较少用到了;
2.2 字符串截取
这个功能就应该很多人都用过了
常用口诀:% 和# 都是数量多就是最大匹配,数量少就是最小匹配。#在键盘左边就是去掉左边,%在右边就是去掉右边
${testfile#*/}、${testfile##*/}、${testfile%/*}、${testfile%%/*}
[root@omp-test-201-93 ~]# tes="a/b/c/d.txt"
[root@omp-test-201-93 ~]# echo ${tes%/*}
a/b/c
[root@omp-test-201-93 ~]# echo ${tes%%/*}
a
[root@omp-test-201-93 ~]# echo ${tes##*/}
d.txt
[root@omp-test-201-93 ~]# echo ${tes#*/}
b/c/d.txt
2.3 字符串替换
${var:num}、${var:num1:num2}
[root@omp-test-201-93 ~]# var="abcdefa"
#0开始,截取下标2以后得字符
[root@omp-test-201-93 ~]# echo ${var:2}
cdefa
#从下标2开始读取3个字符
[root@omp-test-201-93 ~]# echo ${var:2:3}
cde
#从后面截取两个字符
[root@omp-test-201-93 ~]# echo ${var: -2}
fa
#从后面解决-2 前面必须要有空格,否则无效
[root@omp-test-201-93 ~]# echo ${var:-2}
abcdefa
#不想写空格用小括号括起来即可
[root@omp-test-201-93 ~]# echo ${var:(-2)}
fa
#替换找到的第一个字符
[root@omp-test-201-93 ~]# echo ${var/a/6}
6bcdefa
#替换找到的全部字符
[root@omp-test-201-93 ~]# echo ${var//a/6}
6bcdef6
2.4 表示一个范围
适用于批量创建多个文件或者文件夹,也可以用于for中
[root@omp-test-201-93 ~]# echo {1..6}
1 2 3 4 5 6
如若转载,请注明出处:https://www.summeng.org/14435.html