bash 变量引用扩展

bash 变量引用扩展

我们都知道,在bash中,若定义了一个变量x=3,则使用${x}来进行变量替换 ,将x的值替换为3,在bash中,为变量替换提供了非常多的功能,下面我们一一来看下:

为不存在的变量赋默认值:

当引用一个不存在的变量的时候,默认会替换为空,比如,当没有定义x这个变量,直接使用它的时候,其结果会为空,案例如下:

bash 复制代码
#!/bin/bash

# 未定义变量x直接使用
echo x: ${x}

上述脚本执行的结果为:

bash 复制代码
# bash var_declaration.sh
x:
#

bash中,可以在变量后添加:=而后是该变量的默认值,这样的话,如果没有定义该变量,那么该变量的默认值则为新的值,比如:

bash 复制代码
#!/bin/bash

# 未定义变量x直接使用
echo x: ${x:=123}
echo x: ${x}

其执行结果为:

bash 复制代码
# bash var_declaration.sh
x: 123
x: 123
#

如上赋予默认值更多使用在接收命令行参数,用户可能并未输入参数,需要给定一个默认值的情况来执行,这样便可以直接进行if判断,而非提前判断是否为空了,脚本如下:

bash 复制代码
#!/bin/bash

operation=$1

echo 执行的选项为:${operation:=none}


if [ ${operation} = "yes" ];then
        echo "yes!!!"
fi

上述脚本,operation的值来源于命令行的第一个参数,如果并没有输入具体的参数,则使用默认值none,而后进行参数判断,如果假设没有给定默认值,那么在进行if字符串判断的时候,没有值和yes字符串做比对,会报错:[: =: unary operator expected

为不存在的变量赋临时值:

上述是为了不存在的变量给定了默认值,若在变量中添加-则表示赋予临时默认值,使用后即失效,例如:

bash 复制代码
#!/bin/bash

echo a: ${a:-5}
echo a: ${a}

上述脚本并没有定义变量a,但是在第一个echo语句的时候,将其变量替换为了5,此时并未重新定义a这个变量,所以第二个echo的时候,会输出为空,其结果为:

bash 复制代码
# bash var_declaration.sh
a: 5
a:
#

这种方式适用于仅判断一次的的脚本,比如,可以将上述脚本修改为这样的:

bash 复制代码
#!/bin/bash

operation=$1

if [ ${operation:-none} = "yes" ];then
        echo "yes!!!"
fi

这样,若operation为空的话,那么参数只在if判断中被赋予none的值,而后依然为空。

为不存在的变量抛错

在工具类脚本中,需要有非常强的健壮性,若某些关键配置缺失,需要报错并且退出脚本,以往我们的做法是直接进行判断,若不存在再exit非标准退出,比如下面这个脚本片段:

bash 复制代码
#!/bin/bash

# x未被定义

if [ -z ${x} ];then
        echo 错误:x未被定义
        exit 1
fi

上述脚本的含义为:若当x未被定义的时候,使用-z进行判断,-z的意思是后面待判断的值为空,则抛错,x未被定义,或者定义了为空,然后使用exit退出程序。

若要判断数十个或者数百个变量,即使使用函数的形式,也有大量的代码,其实在bash中,也为我们提供了类似的功能,比如下面语句可以完全代替上述语句块:

bash 复制代码
#!/bin/bash

# x未被定义
${x:?x未被定义或者为空}

echo "456"

直接使用:?关键字来判断,当x未被定义的时候,就对后面语句进行错误输出。且中断程序执行,直接退出,退出状态码为1。执行后结果为:

bash 复制代码
# bash var_declaration.sh
var_declaration.sh: line 4: x: x未被定义或者为空
# echo $?
1
#

上述结果,当判断x未被定义的时候,就进行预定义的错误输出,且退出程序,不会执行后续语句,最后的退出状态码为1。效果和上述使用if来判断一致(上述使用if判断是标准输出,这里是错误输出)。

字符串切片

bash中,可以对字符串进行切片处理,其用法为:

bash 复制代码
${待处理的字符串变量:偏移量[:长度]}

其中,长度部分是可选的;如果不写长度的话,则默认会截取到字符串的末尾。

当偏移量小于0的时候,默认会从第 0 位开始截取;若当长度为负数时,则表示从字符串末尾向前回退相应的字符数来进行截取。

这里需要注意的时,字符串起始是0,而非1

案例如下:

bash 复制代码
x="abcedf"

echo ${x:0}

上述代码表示x的值为abcedf,输出的时候,设置偏移量为0,长度没有写,则默认长度,所以最后输出的结果为:

bash 复制代码
abcedf

若想截图3个字符,则只需将长度设置为3即可:

bash 复制代码
x="abcedf"

echo ${x:0:3}

上述代码的结果为:

bash 复制代码
abc

从想直接截取到最后的2个字符前,只需要将长度设置为-2即可,例如:

bash 复制代码
x="abcedf"

echo ${x:0:-2}

其结果为:

bash 复制代码
abce

若调整了偏移量,假设为2,则表示从第二位开始截取,截取的长度由后面的参数来决定,比如:

bash 复制代码
x="abcedf"

echo ${x:1:3}

上面代码表示从字符串的第1位开始截取,截取的长度为3

字符串匹配删除

bash中,不仅可以对字符串进行切片,还能进行匹配删除,匹配可以分为惰性匹配和贪婪匹配,当然在bash中称为是最短匹配最长匹配

字符串匹配删除的语法为:

bash 复制代码
${待处理的字符串变量#最短删除规则}
${待处理的字符串变量##最长删除规则}

这里所指的规则可以是普通字符串,也可以是匹配模式。这个匹配模式,不同于正则表达式,这里暂时不做讲述。回到字符串匹配删除这里来。

比如有如下字符串:

bash 复制代码
x=dabcabcabcef

比如想要删除abc,可以这样使用:

bash 复制代码
x=dabcabcabcef

echo ${x#*abc}
echo ${x##*abc}

上述删除规则为*abc,其中*表示匹配任意个字符,对于字符串dabcabcabcef而言,*abc可以匹配为abc字符串本身,也可以匹配为dabc,也可以匹配为dabcabcabc,只要是出现abc的,前面都可以被匹配到。

所以最短匹配删除的语句是${x#*abc},对于dabcabcabcef字符串而言,*abc表示从开头开始,匹配到第一个出现的abc字符串,即:dabc

而对于最长匹配删除的语句是${x##*abc},对于字符串dabcabcabcef而言,*abc表示从开头开始,匹配到最后一个abc字符串,即:dabcabcabc

所以,该脚本执行的结果为:

bash 复制代码
# bash var_declaration.sh
abcabcef
ef
#

总结

bash中,已经为我们提供了变量提供了很多的操作,包括判断变量是否已经赋值,为不存在的变量抛错等,提供了字符串切片,匹配删除等,无需自己亲自动手实现,只需要调用语法,便可以轻松完成这些步骤,当然bash变量引用扩展还不止如此,由于篇幅有限,就介绍到这里,剩下的后面有机会再详细介绍。

相关推荐
wusam8 小时前
Linux系统管理与编程24:基础条件准备-混搭“本地+阿里云”yum源
linux·运维·阿里云·shell
Johny_Zhao13 小时前
企业级MediaWiki知识库系统搭建部署指南(CentOS 8)
linux·网络·网络安全·信息安全·云计算·shell·yum源·系统运维·itsm·mediawiki·企业知识库搭建
粉红色回忆2 天前
# bash新手入门指南-特殊变量的使用
shell
linux-hzh2 天前
Shell 脚本
linux·shell
wusam7 天前
Linux系统管理与编程23:巧用git资源一键部署LAMP
linux·运维·git·shell·lamp
Johny_Zhao8 天前
Nmap 从入门到精通:详细指南
linux·网络·网络安全·信息安全·云计算·shell·nmap·yum源·系统运维·itsm
Strugglingler9 天前
Linux shell 正则表达式高效使用
linux·shell
Johny_Zhao9 天前
centos8安装部署RADIUS+MySQLPGSQL高可用架构实现
linux·网络·网络安全·信息安全·云计算·shell·cisco·yum源·radius·huawei·系统运维·华三
纪伊路上盛名在9 天前
python、R、shell兼容1
开发语言·python·jupyter·r语言·shell·生物信息·效率