Bash 字符串操作
Bash 字符串操作
Bash 中大部分的变量包括文件都可以当作字符串进行操作,因此本章的内容非常实用
字符串的长度
获取字符串长度的语法如下。
|
|
下面是一个例子。引号中的字符串也算长度。
|
|
大括号{}
是必需的,否则 Bash 会将$#
理解成脚本的参数个数,将变量名理解成文本。
|
|
上面例子中,Bash 将$#
和myvar
分开解释了。
关于
$#
的分析,请看《Bash 脚本》
子字符串
字符串提取子串的语法如下。
|
|
上面语法的含义是返回变量$varname
的子字符串,
首先我们需要明白一个下标定义,从左往右数,即正序的时候,第一个字符的下标是 0,从右往左数,即倒序的时候,第一个数的下标是 -1。
-
offset
为正数-
length
为正数的时候,length
的意义为字串的长度,表达式的的作用:是返回varname
按正序从位置offset
开始,包含offset
位置的字符,往右数长度为length
,的子串。 -
length
为负数的时候,length
的意义为last_offset
,表示子串中最后一个字符的位置,且不包含,表达式的的作用:是返回varname
按正序从位置offset
开始,包含offset
位置的字符,到按倒叙位置为last_offset
,不包含last_offset
位置的字符,的子串。 -
如果省略
length
,则从位置offset
开始,一直返回到字符串的结尾。
-
-
offset
为负数,如果offset
为负值,表示按倒叙定位。注意,负数前面必须有一个空格,以防止与${variable:-word}
的变量的设置默认值语法混淆。关于${variable:-word}
的语法,请看《Bash 变量》的检查变量的值是否为空
小节。-
length
为正数的时候,length
的意义为字串的长度,表达式的的作用:是返回varname
按倒叙从位置offset
开始,包含offset
位置的字符,往右数长度为长度为length
,的子串。 -
length
为负数的时候,length
的意义为last_offset
,表示子串中最后一个字符的位置,且不包含,表达式的的作用:是返回varname
按倒叙从位置offset
开始,包含offset
位置的字符,到按倒叙位置为last_offset
,不包含last_offset
位置的字符,的子串。 -
如果省略
length
,则从位置offset
开始,一直返回到字符串的结尾。
-
|
|
我们可以通过一个变量来接受子字符串。获取子字符串的操作不会修改原字符串
|
|
注意,不能直接对字符串字面量进行获取子字符串的操作,只能对值为字符串的变量执行获取子字符串的操作
|
|
字符串拼接
字符串的拼接很简单,直接写在一起即可
双引号字符串的拼接
|
|
输出
|
|
单引号字符串的拼接
|
|
输出
|
|
查找字符所在的位置
|
|
《Bash 的算术运算》的
expr 命令
小节
搜索和替换
Bash 提供多种模式的匹配和替换的方法
字符串头部的模式匹配
-
${variable#pattern}
如果 pattern 匹配变量 variable 的开头,删除最短匹配(非贪婪匹配)的部分,返回剩余部分,原字符串不会有变化 -
${variable##pattern}
如果 pattern 匹配变量 variable 的开头,删除最长匹配(贪婪匹配)的部分,返回剩余部分,原字符串不会有变化 -
${variable/#pattern/string}
如果 pattern 匹配变量 variable 的开头,就会将最长匹配(贪婪匹配)的部分替换成 string,原字符串不会有变化
不存在语法
${variable/##pattern/string}
${variable#pattern}
和${variable##pattern}
可以理解为/string
中的string
为空字符串。默认将匹配部分替换成空字符串,也就是删除
匹配模式pattern
可以使用*
、?
、[]
等通配符。
如果字符串里面无法匹配模式pattern
,则对字符串不会发生任何修改,最终返回原字符串。
简单实践一下:
|
|
常用用法,比如只获取文件名称(包括拓展名)、仅获取文件拓展类型、仅获取文件名(不包括拓展类型)
|
|
其实我们可以通过dirname
获取文件全路径中的路径部分,通过basename
命令获得文件全路径中的文件名(包含文件类型后缀)的部分
-
dirname
:该命令可以取给定路径的目录部分(strip non-directory suffix from file name)。这个命令很少直接在 shell 命令行中使用,我们一般把它用在 shell 脚本中,用于取得脚本文件所在目录,然后将当前目录切换过去。
在脚本中可以这样写
1
cd $(dirname "$0") || exit 1
-
basename
:basename 命令用于去掉文件名的目录和后缀(strip directory and suffix from filenames),对应的 dirname 命令用于截取目录,basename
也经常用于在脚本中获取脚本的文件名1
echo $(basename "$0")
简单实践:
|
|
字符串尾部的模式匹配
语法跟字符串头部匹配差不多,就是把#
换成了%
:
-
${variable%pattern}
如果 pattern 匹配变量 variable 的结尾,删除最短匹配(非贪婪匹配)的部分,返回剩余部分,原字符串不会有变化 -
${variable%%pattern}
如果 pattern 匹配变量 variable 的结尾,删除最长匹配(贪婪匹配)的部分,返回剩余部分,原字符串不会有变化 -
${variable/%pattern/string}
如果 pattern 匹配变量 variable 的结尾,就会将最长匹配(贪婪匹配)的部分替换成 string,原字符串不会有变化
不存在语法
${variable/%%pattern/string}
${variable%pattern}
和${variable%%pattern}
可以理解为/string
中的string
为空字符串。默认将匹配部分替换成空字符串,也就是删除
匹配模式pattern
可以使用*
、?
、[]
等通配符。
如果字符串里面无法匹配模式pattern
,则对字符串不会发生任何修改,最终返回原字符串。
简单实践:
|
|
常用用法,比如只获取文件名称(包括拓展名)、仅获取文件拓展类型、仅获取文件名(不包括拓展类型)
具体实践请看字符串头部的模式匹配
小节
任意位置的模式匹配
-
${variable/pattern/string}
如果 pattern 匹配变量 variable 的一部分,最长匹配(贪婪匹配)的那部分被 string 替换,但仅替换第一个匹配 -
${variable//pattern/string}
如果 pattern 匹配变量 variable 的一部分,最长匹配(贪婪匹配)的那部分被 string 替换,所有匹配都替换
上面两种语法都是最长匹配(贪婪匹配)下的替换,区别是前一个语法仅仅替换第一个匹配,后一个语法替换所有匹配。
|
|
一个简单的应用是看 PATH 环境变量
将:
替换成换行,然后可以一行一个路径,看着束缚很多
这个其实给了我们一种将单个字符串拆分成多行的思路,拆分成多行之后,再一行一行地读取到数组中。
|
|
将单行字符串变成数组
关于数组的知识,请看《Bash 数组》
|
|
此外还有两种特殊形式,我们在字符串头部的模式匹配
和字符串尾部的模式匹配
中实际上就已经学习过了
|
|
改变大小写
-
${varname^^}
转为大写 -
${varname,,}
转为小写
简单实践
|
|