文章目录


参考书籍:《Linux Shell核心编程指南》——丁明一

一、花括号{}

注意:花括号不可以被引号引用

echo {a..h}
echo {1..9}
echo {1..9..2} #1到9,步长为2

Shell八大扩展详解_文件描述符

mkdir -p test/{aa,bb}

Shell八大扩展详解_进程替换_02

cp /etc/hosts{,.bak}    #利用扩展,备份文件
mv /etc/hosts.bak{,hosts_bak} #重命名

二、波浪号~

波浪号在Shell脚本中默认代表当前用户的家目录

echo ~      #显示当前用户的家目录
ls ~devops #查看devops用户的家目录

Shell八大扩展详解_bash_03
~+表示当前工作目录,~-表示上一个工作目录
Shell八大扩展详解_字符串切割_04

三、变量替换

​3.1.获取变量的值​

a=123
echo ${a}

​shell通过变量的值,获取这个值的值​

​3.2.变量测试​

Shell八大扩展详解_进程替换_05
test的值未定义,则返回关键字123,并赋值给变量test,通常用于给变量设置默认值
Shell八大扩展详解_字符串切割_06
实现脚本的报错功能,判断一个变量是否有值,没有值或者值为空时就可以返回特定的报错信息,退出状态码为非0
echo ${input:?‘没有输入变量的值’}
Shell八大扩展详解_字符串切割_07
与前面相反的示例,当变量没有定义或者为空时,返回空;当变量有值且非空时,返回关键字
Shell八大扩展详解_进程替换_08
设置key=123后,返回关键字value

​3.3.字符串切割与掐头去尾​

Shell八大扩展详解_进程替换_09
Shell八大扩展详解_bash_10
注意:这几种对变量的替换方式,都不会改变变量自身的值

[root@localhost tmp]# value="hello world"
[root@localhost tmp]# echo ${value:2} #从位置2截取到末尾,位置默认从0开始
llo world
[root@localhost tmp]# echo ${value:2:3} #从位置2开始,截取后面3个字符
llo

使用#号可以掐头,使用%号可以去尾

[root@localhost ~]# value="192.168.1.2:5000/root/nginx:1.16"
[root@localhost ~]# echo ${value#*:} #匹配第一个:及其左边的所有内容并删除
5000/root/nginx:1.16
[root@localhost ~]# echo ${value##*:} #掐头最长匹配,删除最后一个:号及其左边的所有内容
1.16
[root@localhost ~]# echo ${value%:*} #从右边开始匹配
192.168.1.2:5000/root/nginx
[root@localhost ~]# echo ${value%%:*} #去尾最长匹配
192.168.1.2

​3.4.变量内容的统计与替换​

Shell八大扩展详解_bash_11

[root@localhost ~]# echo ${!U@}   #列出以U开头的所有变量
UID USER

[root@localhost ~]# array1=(11 22 33) #定义普通数组
[root@localhost ~]# echo ${!array1[@]} #返回数组下标
0 1 2

[root@localhost ~]# key="hello world"
[root@localhost ~]# echo ${#key} #统计变量长度
11

[root@localhost ~]# phone=1231121
[root@localhost ~]# echo ${phone/1/x} #将1替换为x,仅替换第一个
x231121
[root@localhost ~]# echo ${phone//1/x} #把所有的1替换为x
x23xx2x

[root@localhost ~]# word="i love you"
[root@localhost ~]# echo ${word^} #将首字母替换为大写
I love you
[root@localhost ~]# echo ${word^^} #将所有字母替换为大写
I LOVE YOU
[root@localhost ~]# echo ${word^o} #将第一个o替换为大写,但并未生效,只能匹配第一个字母,而第一个字母是i
i love you
[root@localhost ~]# echo ${word^^o} #将所有o替换为大写
i lOve yOu
[root@localhost ~]# echo ${word^^[ilo]} #将所有字母i、l、o替换为大写
I LOve yOu

[root@localhost ~]# test="HELLO WORLD"
[root@localhost ~]# echo ${test,} #将首字母替换为小写
hELLO WORLD
[root@localhost ~]# echo ${test,,} #将所有字母替换为小写
hello world
[root@localhost ~]# echo ${test,,[HL]} #将所有H、L替换为小写
hEllO WORlD

四、命令替换

可以通过$(命令)或者`命令`实现,推荐使用$(命令),该方式支持嵌套的命令替换

[root@localhost ~]# echo "系统当前登录人数:$(who | wc -l)"
系统当前登录人数:1

五、算术替换

算术替换扩展的格式为$(()),也可以使用$[],算术扩展支持嵌套。

[root@localhost ~]# echo $[2+3]
5
[root@localhost ~]# echo $[2*3]
6
[root@localhost ~]# echo $[5-2]
3
[root@localhost ~]# echo $[20/4]
5
[root@localhost ~]# echo $[20%6]
2
[root@localhost ~]# echo $[2**3]
8

六、进程替换

​命令替换​​​是把一个​​命令的输出结果​​​返回并且赋值给变量,而​​进程替换​​​则是把​​进程的返回结果​​​通过​​文件描述符​​的方式传递给另一个进程。

语法:<(命令)或者>(命令)

一旦使用了进程替换功能,系统将会在/dev/fd目录下创建文件描述符文件,通过该文件描述符将进程的输出结果传递给其他进程。

​示例一​

Shell八大扩展详解_进程替换_12
解释:
<(who)会将who命令产生的结果保存到​​​/dev/fd/63​​这个文件描述符中,并将该文件描述符作为wc -l命令的输入参数,最终wc -l<(who)的输出结果说明在/dev/fd/63这个文件中包含1行内容。

需注意:
文件描述符是动态生成的,所以当进程执行完毕,再使用ls查看该文件描述符时会提示没有该文件

​示例二​

将多个进程的输出结果传递给一个进程作为其输入参数;每个进程替换都会创建一个文件描述符

paste <(cut -d: -f1 /etc/passwd) <(cut -d: -f2 /etc/shadow)

Shell八大扩展详解_命令替换_13
提取/etc/passwd的第一列和/etc/shadow中的第二列,通过paste命令将数据合并为一个文件信息。
paste命令会逐行读取多个文件的内容并将多个文件合并

​示例三​

[root@localhost tmp]# touch {a,b,c}.sh
[root@localhost tmp]# touch {1,2,3}.conf
[root@localhost tmp]# ls | tee >(grep sh$ >sh.log) >(grep conf$ > conf.log)

Shell八大扩展详解_字符串切割_14
将sh结尾的文件名重定向到sh.log文件,将conf结尾的文件名重定向到conf.log文件

七、单词切割

单词切割也叫分词,使用IFS变量进行分词处理。如果没有自定义IFS,则默认值为空格、Tab制表符和换行符

​详解shell IFS​

八、路径替换

set -f可以禁用路径替换,禁用后Bash不会在路径和文件名中搜索*、?和[符号

使用shopt命令时开启了​​nocaseglob选项​​​,则Bash在进行模式匹配时​​不区分大小写​​​,默认区分大小写。
shopt命令开启​​​extglob选项​​​,可以让Bash支持​​扩展通配符​​,默认开启

shopt -s开启特定的Shell属性,shopt -u关闭特定的Shell属性

[root@localhost tmp]# touch {a,A}.txt
[root@localhost tmp]# ls a* #区分大小写
a.txt
[root@localhost tmp]# shopt -s nocaseglob #设置不区分大小写
[root@localhost tmp]# ls a*
a.txt A.txt
[root@localhost tmp]# shopt -u nocaseglob #关闭忽略大小写属性
[root@localhost tmp]# shopt nocaseglob
nocaseglob off