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

Posted 二木成林

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux拓展之Shell变量扩展${}相关的知识,希望对你有一定的参考价值。

概述

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



语法

声明变量的语法如下:

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

获取变量值的语法如下:

# 语法一,使用引号引起来是为了避免因为变量中有空格导致出现错误
echo "$变量名"
# 示例一
echo "$msg"

# 语法二,printf 命令也可以输出内容,但不会自动换行,需要通过转义符 \\n 进行换行
printf "$变量名"
# 示例
printf "$msg\\n"

如果要对变量进行扩展,就可以使用 $ 语法,格式如下:

# 语法,不进行变量扩展时等价于 "$变量名"
$变量名
# 示例
echo "$msg"



使用

设置默认 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."

查找字符串长度

如果要查找一个字符串变量的长度,语法格式如下:

# 语法
$#变量名

# 示例
msg="hello world"
len=$#msg
echo $len

移除模式

可以移除字符串变量中前面的子串(从前往后)。语法格式如下:

# 语法:可以从变量前面开始移除匹配模式匹配到的所有字符
# 删除匹配模式匹配到的最短部分,非贪婪匹配
$变量名#匹配模式
# 删除匹配模式匹配到的最长部分,贪婪匹配
$变量名##匹配模式

# 示例,获取路径所表示的文件后缀
path="/root/src/tar/test.tar.gz"
echo "$path#*." # 非贪婪匹配,* 属于通配符,匹配第一个 . 字符前面的所有内容,即会删除第一个 . 字符之前的所有内容,包括 . 字符本身
# 示例,只获取如下路径所表示的文件名
path="/root/src/tar/test.tar.gz"
echo "$path##*/" # 贪婪匹配,* 属于通配符,匹配最后一个 / 字符前面的所有内容,即会删除最后一个 / 字符之前的所有内容,包括 / 字符本身

可以移除字符串变量中后面的子串(从后往前)。语法格式如下:

# 语法:可以从变量后面开始移除匹配模式匹配到的所有字符
# 删除匹配模式匹配到的最短部分,非贪婪匹配
$变量名%匹配模式
# 删除匹配模式匹配到的最长部分,贪婪匹配
$变量名%%匹配模式

# 示例,获取路径所表示的文件父目录
path="/root/src/tar/test.tar.gz"
echo "$path%/*.tar.gz" # 非贪婪匹配,* 属于通配符,匹配 /test.tar.gz,会删除该字符串获取到该文件的父目录
# 示例,只获取所表示的文件名而去除掉后缀
file="test.tar.gz"
echo "$file%%.*" # 贪婪匹配,* 属于通配符,会从后往前找到最后一个 . 字符,然后删除 . 字符及之后的所有字符,留下文件名

查找和替换

可以查找到旧字符串然后替换成新字符串(可以替代 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"

注:会返回修改后的结果,而不是对原变量进行修改。

提取子串

还可以提取子串,表示从 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

注:offset 是从字符串的第 1 个字符开始的。

获取匹配的变量名列表

可以获取名称以指定前缀开头的所有变量名称。语法格式如下:

# 语法
$!指定变量前缀匹配模式

# 示例
name1="唐僧"
name2="孙悟空"
name3="猪八戒"
echo "$!name*"

转换大小写

可以将字母转换成大写或小写。语法格式如下:

# 语法,将第一个字符转换为大写
$变量名^
# 语法,将所有字母都转换成大写
$变量名^^
# 语法,将第一个字符转换为小写
$变量名,
# 语法,将所有字母都转换成小写
$变量名,,
# 语法,仅转换第一个字符为小写
$变量名,指定第一个字符

# 示例,将第一个字符转换为大写
msg="hello"
echo $msg^
# 示例,将所有字母都转换成大写
echo $msg^^
# 示例,将第一个字符转换为小写
msg="HELLO"
echo $msg,
# 示例,将所有字母都转换成小写
echo $msg,,
# 示例,仅第一个字符是 H 则转换它
echo $msg,H



总结

所有方便的 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 如果匹配成功,才将所有字符转换为大写。

参考资料:

以上是关于Linux拓展之Shell变量扩展${}的主要内容,如果未能解决你的问题,请参考以下文章

Linux拓展之使用 shell 进行数学运算

Linux拓展之Shell中求字符串的长度

Linux拓展之Shell中函数的返回值

Linux拓展之调试脚本

Linux之逻辑卷的管理与创建(记不住就多敲几次)

Linux拓展之产生随机数