1.字符串长度
${#varname}
大括号{}
是必需的,否则 Bash 会将$#
理解成脚本的参数个数,将变量名理解成文本。
2.子字符串
${varname:offset:length}
上面语法的含义是返回变量$varname
的子字符串,从位置offset
开始(从0
开始计算),长度为length
。
这种语法不能直接操作字符串,只能通过变量来读取字符串,并且不会改变原始字符串
如果省略length
,则从位置offset
开始,一直返回到字符串的结尾。
如果offset
为负值,表示从字符串的末尾开始算起。注意,负数前面必须有一个空格, 以防止与${variable:-word}
的变量的设置默认值语法(如果variable设置了值就是值,如果没设置值就是word)混淆。这时还可以指定length
,length
可以是正值,也可以是负值(负值不能超过offset
的长度)。
$ foo="This string is long."
$ echo ${foo: -5}
long.
$ echo ${foo: -5:2}
lo
$ echo ${foo: -5:-2}
lon
上面例子中,offset
为-5
,表示从倒数第5个字符开始截取,所以返回long.
。如果指定长度length
为2
,则返回lo
;如果length
为-2
,表示要排除从字符串末尾开始的2个字符,所以返回lon
。
3.搜索和替换
Bash提供字符串搜索和替换得多种方法。
(1)字符串头部的模式匹配
以下两种语法可以检查字符串开头,是否匹配给定的模式。如果匹配成功,就删除匹配的部分,返回剩下的部分。原始变量不会发生变化。
# 如果 pattern 匹配变量 variable 的开头,
# 删除最短匹配(非贪婪匹配)的部分,返回剩余部分
${variable#pattern}
# 如果 pattern 匹配变量 variable 的开头,
# 删除最长匹配(贪婪匹配)的部分,返回剩余部分
${variable##pattern}
上面两种语法会删除变量字符串开头的匹配部分(将其替换为空),返回剩下的部分。区别是一个是最短匹配(又称非贪婪匹配),另一个是最长匹配(又称贪婪匹配)。
匹配模式pattern
可以使用*
、?
、[]
等通配符。
$ phone="555-456-1414"
$ echo ${phone#*-}
456-1414
$ echo ${phone##*-}
1414
如果匹配不成功,则返回原始字符串。
如果要将头部匹配的部分,替换成其他内容,采用下面的写法。
# 模式必须出现在字符串的开头
${variable/#pattern/string}
# 示例
$ foo=JPG.JPG
$ echo ${foo/#JPG/jpg}
jpg.JPG
(2)字符串尾部得模式匹配
以下两种语法可以检查字符串结尾,是否匹配给定的模式。如果匹配成功,就删除匹配的部分,返回剩下的部分。原始变量不会发生变化。
# 如果 pattern 匹配变量 variable 的结尾,
# 删除最短匹配(非贪婪匹配)的部分,返回剩余部分
${variable%pattern}
# 如果 pattern 匹配变量 variable 的结尾,
# 删除最长匹配(贪婪匹配)的部分,返回剩余部分
${variable%%pattern}
上面两种语法会删除变量字符串结尾的匹配部分(将其替换为空),返回剩下的部分。区别是一个是最短匹配(又称非贪婪匹配),另一个是最长匹配(又称贪婪匹配)。
$ path=/home/cam/book/long.file.name
$ echo ${path%.*}
/home/cam/book/long.file
$ echo ${path%%.*}
/home/cam/book/long
上面例子中,匹配模式是.*
,其中*
可以匹配任意数量的字符,所以最短匹配是.name
,最长匹配是.file.name
。
(3)任意位置的模式匹配
以下两种语法可以检查字符串内部,是否匹配给定的模式。如果匹配成功,就删除匹配的部分,换成其他的字符串返回。原始变量不会发生变化。
# 如果 pattern 匹配变量 variable 的一部分,
# 最长匹配(贪婪匹配)的那部分被 string 替换,但仅替换第一个匹配
${variable/pattern/string}
# 如果 pattern 匹配变量 variable 的一部分,
# 最长匹配(贪婪匹配)的那部分被 string 替换,所有匹配都替换
${variable//pattern/string}
上面两种语法都是最长匹配(贪婪匹配)下的替换,区别是前一个语法仅仅替换第一个匹配,后一个语法替换所有匹配。
$ path=/home/cam/foo/foo.name
$ echo ${path/foo/bar}
/home/cam/bar/foo.name
$ echo ${path//foo/bar}
/home/cam/bar/bar.name
模式部分可以使用通配符。
$ phone="555-456-1414"
$ echo ${phone/5?4/-}
55-56-1414
上面的例子将5-4
替换成-
。
4.改变大小写
# 转为大写
${varname^^}
# 转为小写
${varname,,}