#|Linux拓展之Shell变量扩展${}

概述 在 Shell 中 $ 字符可以用于参数扩展,算术扩展和命令替换。可以根据需要使用它来操作和扩展变量,而无需使用 sedawk 等外部命令。


语法 声明变量的语法如下:

# 语法 变量名=变量值 # 示例 msg="hello world"

获取变量值的语法如下:
# 语法一,使用引号引起来是为了避免因为变量中有空格导致出现错误 echo "$变量名" # 示例一 echo "$msg"# 语法二,printf 命令也可以输出内容,但不会自动换行,需要通过转义符 \n 进行换行 printf "$变量名" # 示例 printf "$msg\n"

如果要对变量进行扩展,就可以使用 ${} 语法,格式如下:
# 语法,不进行变量扩展时等价于 "$变量名" ${变量名} # 示例 echo "${msg}"

#|Linux拓展之Shell变量扩展${}
文章图片



使用 设置默认 Shell 变量值
我们可以为变量设置默认值,语法格式如下:
# 语法 ${变量名:-默认值} ${变量名:=默认值} # 示例 res=${msg:-"hello world"} res=${msg:="hello world"}

关于它们的使用及区别,详情可参考:Linux拓展之Shell默认变量值。
检测变量是否定义
我们可以设置如果变量未定义或者位置参数未传递,则可以用如下语法停止执行脚本,以免报错。命令格式如下:
# 语法 # 如果变量未定义 ${变量名?变量未定义输出的提示信息} # 如果变量未定义或者为空字符串 ${变量名:?变量未定义输出的提示信息} # 未传递位置参数,通常用在脚本或函数中 ${位置参数名:?未传递位置参数输出的提示信息}# 示例 # 如果变量未定义 res=${msg?"变量未定义"} # 如果变量未定义或者为空字符串 res=${msg:?"变量未定义或为空"} # 未传递位置参数,通常用在脚本或函数中,$1、$2 等表示接收第 1、2 个参数 res=${1:?"未传递位置参数"} # 提示信息中也可以使用变量扩展 info="未定义的变量" res=${msg:?"Error: ${info}."}

#|Linux拓展之Shell变量扩展${}
文章图片

查找字符串长度
如果要查找一个字符串变量的长度,语法格式如下:
# 语法 ${#变量名}# 示例 msg="hello world" len=${#msg} echo $len

#|Linux拓展之Shell变量扩展${}
文章图片

移除模式
可以移除字符串变量中前面的子串(从前往后)。语法格式如下:
# 语法:可以从变量前面开始移除匹配模式匹配到的所有字符 # 删除匹配模式匹配到的最短部分,非贪婪匹配 ${变量名#匹配模式} # 删除匹配模式匹配到的最长部分,贪婪匹配 ${变量名##匹配模式}# 示例,获取路径所表示的文件后缀 path="/root/src/tar/test.tar.gz" echo "${path#*.}" # 非贪婪匹配,* 属于通配符,匹配第一个 . 字符前面的所有内容,即会删除第一个 . 字符之前的所有内容,包括 . 字符本身 # 示例,只获取如下路径所表示的文件名 path="/root/src/tar/test.tar.gz" echo "${path##*/}" # 贪婪匹配,* 属于通配符,匹配最后一个 / 字符前面的所有内容,即会删除最后一个 / 字符之前的所有内容,包括 / 字符本身

#|Linux拓展之Shell变量扩展${}
文章图片

可以移除字符串变量中后面的子串(从后往前)。语法格式如下:
# 语法:可以从变量后面开始移除匹配模式匹配到的所有字符 # 删除匹配模式匹配到的最短部分,非贪婪匹配 ${变量名%匹配模式} # 删除匹配模式匹配到的最长部分,贪婪匹配 ${变量名%%匹配模式}# 示例,获取路径所表示的文件父目录 path="/root/src/tar/test.tar.gz" echo "${path%/*.tar.gz}" # 非贪婪匹配,* 属于通配符,匹配 /test.tar.gz,会删除该字符串获取到该文件的父目录 # 示例,只获取所表示的文件名而去除掉后缀 file="test.tar.gz" echo "${file%%.*}" # 贪婪匹配,* 属于通配符,会从后往前找到最后一个 . 字符,然后删除 . 字符及之后的所有字符,留下文件名

#|Linux拓展之Shell变量扩展${}
文章图片

查找和替换
可以查找到旧字符串然后替换成新字符串(可以替代 sed 命令)。语法格式如下:
# 语法,只会替换第一次匹配成功的字符串 ${变量名/旧字符串匹配模式/新字符串} # 语法,替换所有匹配成功的字符串 ${变量名//旧字符串匹配模式/新字符串}# 示例 var="hello world, hello linux." # 替换变量 var 中的 hello 为 HELLO out=${var/hello/HELLO} echo $out echo $var # 替换变量 var 中的 world 为 java out=${var/world/java} echo $out echo $var # 替换变量 var 中的所有 hello 为 HELLO out=${var//hello/HELLO} echo $out echo $var # 对文件进行重命名 path="/root/test.txt" cp "${path}" "${path/.txt/.txt.bak}"

#|Linux拓展之Shell变量扩展${}
文章图片

注:会返回修改后的结果,而不是对原变量进行修改。
提取子串
还可以提取子串,表示从 offset 指定的字符开始扩展到参数的最大长度字符。语法格式如下:
# 语法 # 提取从第 offset 个字符开始到字符串结尾的所有字符 ${parameter:offset} # 提取从第 offset 个字符开始的 length 个字符 ${parameter:offset:length} ${variable:position} # 示例1,去除多余的斜线 file="/data.tar.gz" echo ${file:1} # 示例2,提取指定个数的字符 name="www.baidu.com" echo ${name:4:5}

【#|Linux拓展之Shell变量扩展${}】#|Linux拓展之Shell变量扩展${}
文章图片

注:offset 是从字符串的第 1 个字符开始的。
获取匹配的变量名列表
可以获取名称以指定前缀开头的所有变量名称。语法格式如下:
# 语法 ${!指定变量前缀匹配模式}# 示例 name1="唐僧" name2="孙悟空" name3="猪八戒" echo "${!name*}"

#|Linux拓展之Shell变量扩展${}
文章图片

转换大小写
可以将字母转换成大写或小写。语法格式如下:
# 语法,将第一个字符转换为大写 ${变量名^} # 语法,将所有字母都转换成大写 ${变量名^^} # 语法,将第一个字符转换为小写 ${变量名,} # 语法,将所有字母都转换成小写 ${变量名,,} # 语法,仅转换第一个字符为小写 ${变量名,指定第一个字符}# 示例,将第一个字符转换为大写 msg="hello" echo ${msg^} # 示例,将所有字母都转换成大写 echo ${msg^^} # 示例,将第一个字符转换为小写 msg="HELLO" echo ${msg,} # 示例,将所有字母都转换成小写 echo ${msg,,} # 示例,仅第一个字符是 H 则转换它 echo ${msg,H}

#|Linux拓展之Shell变量扩展${}
文章图片



总结 所有方便的 bash 参数替换运算符如下表:
语法 说明
${parameter:-defaultValue} 获取默认 shell 变量值
${parameter:=defaultValue} 设置默认 shell 变量值
${parameter:?"Error Message"} 如果未设置参数,则显示错误消息
${#var} 查找字符串的长度
${var%pattern} 从最短的后端(末端)模式中移除
${var%%pattern} 从最长的后端(末端)图案中移除
${var:num1:num2} 子串
${var#pattern} 从最短的正面图案中移除
${var##pattern} 从最长的正面图案中移除
${var/pattern/string} 查找和替换(仅替换第一次出现)
${var//pattern/string} 查找并替换所有匹配项
${!prefix*} 扩展到名称以前缀开头的变量的名称
${var,} 将第一个字符转换为小写。
${var,pattern} 如果匹配成功,才将第一个字符转换为小写。
${var,,} 将所有字符转换为小写。
${var,,pattern} 如果匹配成功,才将所有字符转换为小写。
${var^} 将第一个字符转换为大写。
${var^pattern} 如果匹配成功,才将第一个字符转换为大写。
${var^^} 将所有字符转换为大写。
${var^^pattern} 如果匹配成功,才将所有字符转换为大写。
参考资料:
  • How To Use Bash Parameter Substitution Like A Pro

    推荐阅读