BashShell 字符串内置许多字符串操作,包括有字符串切割、替换、分割等。
${}
语法举例来说:对于字符串 file=/dir1/dir2/dir3/my.file.txt
,可以用 ${}
分别替换得到不同的值:
${file#*/}
: 删掉第一个 / 及其左边的字符串:dir1/dir2/dir3/my.file.txt
${file##*/}
: 删掉最后一个 / 及其左边的字符串:my.file.txt
${file#*.}
: 删掉第一个 . 及其左边的字符串:file.txt
${file##*.}
: 删掉最后一个 . 及其左边的字符串:txt
${file%/*}
: 删掉最后一个 / 及其右边的字符串:/dir1/dir2/dir3
${file%%/*}
: 删掉第一个 / 及其右边的字符串:(空值)
${file%.*}
: 删掉最后一个 . 及其右边的字符串:/dir1/dir2/dir3/my.file
${file%%.*}
: 删掉第一个 . 及其右边的字符串:/dir1/dir2/dir3/my
记忆方法:
# 是去掉左边(键盘上 # 在 $ 的左边)
% 是去掉右边(键盘上 % 在 $ 的右边)
单一符号是最小匹配;两个符号是最大匹配
对于字符串 file=/dir1/dir2/dir3/my.file.txt
,还可以使用 ${}
语法来进行子串提取和替换:
${file: start: length}
语法:${file: 0: 5}
:提取最左边的 5 个字节:/dir1
${file: 5: 5}
:提取从左往右数第 5 个字节右边的连续 5 个字节:/dir2
${file: 5}
:提取第 5 个字节右边的所有字节:/dir2/dir3/my.file.txt
${file: -8: 4}
:提取从右往左数第 8 个字节右边的连续 4 个字节:file
${file: -8}
:提取从右往左数第 8 个字节右边的所有字节:file.txt
${file/dir/path}
:将第一个 dir
提换为 path
:/path1/dir2/dir3/my.file.txt
${file//dir/path}
:将全部 dir
提换为 path
:/path1/path2/path3/my.file.txt
${#file}
:获取字符串长度:27${}
语法默认使用 IFS 指定的分隔符分隔字符串(即空白符:空格、tab 符、换行符),默认使用空格连接字符串元素。
${str[*]}
:得到数组所有元素作为一个长字符串整体(all of the elements)${str[@]}
:得到数组每一个元素,即子串数组(each of elements)${#str[*]}
:得到数组元素的个数(number of elements)${!str[*]}
:得到数组所有元素的下标(all indexs of elements)${!str[@]}
:得到数组每一个元素的下标(each index of elements)【注】此数组非 Bash Shell 的数组变量,只是为了方便理解而称呼,其本质还是单变量,Bash Shell 对其进行了扩展从而使得解析时呈现不同效果。
${str,,}
:将字符串全部转为小写${str^^}
:将字符串全部转为大写bash shell 下将带有特定分隔符的长字符串分割短字符串数组有很多种方式。
对于长字符串分隔符不是空白符(IFS 默认分隔符为空白符:即空格、tab、换行符)的长字符串,可以通过修改 IFS 环境变量来指定字符串分割规则。比如在 bash shell 中输入以下代码:
IFS=:
_str_="hello:world"
for i in $_str_; do echo $i; done
会得到以下结果:
hello
world
详细参见 IFS变量对加双引号和不加双引号变量的区别对待 。
${}
语法如果不想修改 IFS 环境变量,可以使用上文中的 ${}
语法将长字符串分隔符替换为空白符,这样就可以使用默认的 IFS 环境变量。比如在 bash shell 中输入以下代码:
_str_="hello:world"
for i in ${_str_//:/ }; do echo $i; done
会得到以下结果:
hello
world
[[ ]]
语法[[ -z $str ]]
:判定字符串是否等于空[[ -n $str ]]
:判定字符串是否不等于空[ ]
语法【注】[ ]
不能用来判断字符串相包含;且判断字符串的大小关系时需要使用 `` 转义 < >
,防止 bash shell 将其识别为重定向符号;此外,对于 -z
和 -n
选项,字符串必须要用 ""
包裹,不然可能导致奇怪的问题,建议 []
语法中用到的字符串变量都用 ""
包裹。
[ $str1 = $str2 ]
或 [ $str1 == $str2 ]
:判定字符串是否相等[ $str1 != $str2 ]
:判定字符串是否不等[ $str1 =~ $str2 ]
:判定字符串 str1 是否包含字符串 str2[ $str1 \> $str2 ]
:判定字符串 str1 是否按字典序大于字符串 str2[ $str1 \< $str2 ]
:判定字符串 str1 是否按字典序小于字符串 str2[ -z "$str" ]
:判定字符串是否等于空[ -n "$str" ]
:判定字符串是否不等于空【注】test 语法和 [ ]
语法基本一样,也不能用来判断字符串的相包含,< >
也同样需要转义。二者唯一的区别在于,[ ]
是内建的语法,而 test 是调用外在的程序,因此 [ ]
要比 test 更高效。