九、字符串处理
大小写转化
# 把变量中的第一个字符换成大写 ${test^} # 把变量中的所有小写字母,全部替换为大写 ${test^^} # 把变量中的第一个字符换成小写 ${test,} # 把变量中的所有大写字母,全部替换为小写 ${test,,}
示例
#!/bin/bash # script file name is test.sh test="abcDEF" echo "test^=${test^}" echo "test^^=${test^^}" echo "test,=${test,}" echo "test,,=${test,,}"
如图:
获取字符串长度
${#string}
截取
字符串截取的方式:
字符串截取 格式 使用${}表达式 ${var:起始位置:长度};编号从0开始,可省略 使用expr substr expr substr "$var" 起始位置 长度;起始位置编号从1开始 使用cut工具 echo $var | cut -b 起始位置-结束位置;起始位置编号从1开始
下面详细说明${}表达式 的用法:
# 从string字符串的左边第start个字符开始(不包含第start个字符),向右截取到最后,start从0开始; ${string:start} # 从string字符串的左边第start个字符开始(不包含第start个字符),向右截取length个字符; ${string:start:length} # 从string字符串的右边第start个字符开始(包含第start个字符),向右截取到最后,start从1开始; ${string:0-start} # 从string字符串的右边第start个字符开始(包含第start个字符),向右截取length个字符,start从1开始; ${string:0-start:length}
示例
#!/bin/bash # script file name is test.sh url="https://blog.csdn.net/monarch91" echo "url=${url}" echo "url:8=${url:8}" echo "url:8:4=${url:8:4}" echo "url:0-8=${url:0-8}" echo "url:0-8:4=${url:0-8:4}" echo "url#*c=${url#*c}" echo "url##*c=${url##*c}" echo "url%c*=${url%c*}" echo "url%%c*=${url%%c*}"
如图:
字符串切片实例:
a='abcdefghijklmn'
echo ${#a} #输出字符串a的总长度
14
echo ${a:4} #输出字符串a从0开始数,包含第4个元素之后的所有元素
efghijklmn
echo ${a:4:3} #输出字符串a从0开始数,包含第4个元素之后的3个元素
efg
echo ${a: -4} #从字符串a的右侧向左取4个元素,冒号后必须有一个空字符
klmn
echo ${a:5:-2} #输出字符串a从0开始数,包含第5个元素的向右数的i倒数3个元素,注意这种用法依赖bash版本,尽量别用。
fghijkl
echo ${a: -5:-2} #从字符串a的右侧向左数5个,再向右取到倒数3个字符,注意这种用法依赖bash版本,尽量别用。
jkl
echo ${a: -5:2} #从字符串a的右侧向左数5个,再向右取2个字符
jk
字符串的匹配删除
# 从string字符串左边第一次出现*chars的位置开始,截取*chars右边的所有字符,不包含chars; ${string#*chars} # 从string字符串左边最后一次出现*chars的位置开始,截取*chars右边的所有字符,不包含chars; ${string##*chars} # 从string字符串右边第一次出现chars*的位置开始,截取chars*左边的所有字符,不包含chars; ${string%chars*} # 从string字符串右边最后一次出现chars*的位置开始,截取chars*左边的所有字符,不包含chars; ${string%%*chars*}
解析:
${string#substring} 从变量$string的开头, 删除最短匹配$substring的子串 ${string##substring} 从变量$string的开头, 删除最长匹配$substring的子串 ${string%substring} 从变量$string的结尾, 删除最短匹配$substring的子串 ${string%%substring} 从变量$string的结尾, 删除最长匹配$substring的子串
${var#*word}:其中word可以是指定的任意字符功能:自左而右,查找var变量所存储的字符串中,第一次出现的word, 删除字符串开头至第一次出现word字符之间的所有字符
${var##*word}:同上,贪婪模式,不同的是,删除的是字符串开头至最后一次由word指定的字符之间的所有内容
${var%word*}:其中word可以是指定的任意字符;功能:自右而左,查找var变量所存储的字符串中,第一次出现的word, 删除字符串最后一个字符向左至第一次出现word字符之间的所有字符;
${var%%word*}:同上,只不过删除字符串最右侧的字符向左至最后一次出现word字符之间的所有字符;
字符处理实例:
a='abcdefg_a_fghijklmn' echo ${a#*fg} #从左边开始删,删除起始位置到第一个fg为止,包括fg _a_fghijklmn echo ${a##*fg} #贪婪模式,左边开始删,删除起始位置到最后一个fg为止,包括fg hijklmn echo ${a%fg*} #从右边开始删,删除终点位置到第一个fg为止,包括fg abcdefg_a_ echo ${a%%fg*} #贪婪模式,从右边开始删,删除重点位置到最后一个fg为止,包括fg abcde
例子2:
#!/bin/bash # script file name is test.sh url="https://blog.csdn.net/monarch91" echo "url=${url}" echo "url#*c=${url#*c}" echo "url##*c=${url##*c}" echo "url%c*=${url%c*}" echo "url%%c*=${url%%c*}"
字符串的替换
${string/substring/replacement} 使用replacement, 来代替第一个匹配的$substring ${string//substring/replacement} 使用replacement, 代替所有匹配的substring ${string/#substring/replacement} 如果string的前缀匹配substring, 那么就用replacement来代替匹配到的substring ${string/%substring/replacement} 如果string的后缀匹配substring, 那么就用replacement来代替匹配到的substring
${var/pattern/substr}:查找var所表示的字符串中,第一次被pattern所匹配到的字符串,以substr替换之
${var//pattern/substr}: 查找var所表示的字符串中,所有能被pattern所匹配到的字符串,以substr替换之
${var/#pattern/substr}:查找var所表示的字符串中,行首被pattern所匹配到的字符串,以substr替换之
${var/%pattern/substr}:查找var所表示的字符串中,行尾被pattern所匹配到的字符串,以substr替换之
查找替换实例:
a='abcdefg_a_fghijklmn' echo ${a/fg/dd} #替换从左边数第一个fg为dd abcdedd_a_fghijklmn echo ${a//fg/dd} #替换字符串中所有的fg为dd abcdedd_a_ddhijklmn echo ${a/#ab/dd} #如果开头是ab则替换成dd ddcdefg_a_fghijklmn echo ${a/#fd/dd} #如果开头是fd则替换成dd abcdefg_a_fghijklmn #开头不是fd不做替换 echo ${a/%mn/dd} #结尾是mn则替换成dd abcdefg_a_fghijkldd echo ${a/%fd/dd} #如果结尾是fd则替换成dd abcdefg_a_fghijklmn #结尾并不是fd不做替换
变量初值处理
# 若变量var为空,则用string来替换此处的值,最常用。
${var:-string}
# 若变量var为空,则用string来替换此处的值,把string赋给变量var。
${var:=string}
# 若变量var不为空,则用string来替换此处的值。
${var:+string}
# 若变量var不为空,则用string来替换此处的值;
# 若变量var为空,则把string输出到标准错误中,并从脚本中退出。
# 常用利用此特性来检查是否设置了变量的值。
${var:?string}
取值
取值,${var:-word}
若变量var已存在且非null,则返回$var的值 否则返回字串"word",变量var值不变 用途: 如果变量没定义 返回默认值
赋值
赋值,${var:=word}
若变量var已存在且非null,则返回$var的值 否则返回字串"word",并赋值给变量var 用途: 如果变量没定义 给变量赋值
有值时提示
有值时提示,${var:+"提示信息"}
若变量var已存在且非null,则给出提示
否则返回NUll(空值)
用途 : 测试变量是否定义
无值时提示
无值时提示,${var:?"提示信息"}
若变量var已存在且非null,则返回$var的值
否则给出提示信息(若省略,则用默认提示)
用途: 捕捉由于变量未定义所导致的错误
下面一次举例说明:
(1)${value:-word}
当变量未定义或者值为空时,返回值为word内容,否则返回变量的值
举例:
[zgy@Web ~]$ result=${test:-UNSET} [zgy@Web ~]$ echo $result UNSET [zgy@Web ~]$ echo $test ==>这里是空
结论:当test变量没内容时,就返回了后面的UNSET.
[zgy@Web ~]$ test='oldboy' [zgy@Web ~]$ result=${test:-UNSET} [zgy@Web ~]$ echo $result Oldboy
提示:这个变量可以用来判断变量是否没有定义
(2)${value:=word}
[zgy@Web ~]$ unset result [zgy@Web ~]$ echo $result [zgy@Web ~]$ unset test [zgy@Web ~]$ echo $test [zgy@Web ~]$ result=${test:=UNSET} [zgy@Web ~]$ echo $result UNSET [zgy@Web ~]$ echo $test UNSET [zgy@Web ~]$ test=oldboy [zgy@Web ~]$ result=${test:=UNSET} [zgy@Web ~]$ echo $result oldboy [zgy@Web ~]$ echo $test Oldboy
提示:这个变量功能可以解决变量没有定义的问题,确保变量始终有值
(3)${value:?”word”}
[zgy@Web ~]$ echo ${value:?"not defined"} -bash: value: not defined [zgy@Web ~]$ value=1 [zgy@Web ~]$ echo ${value:?"not defined"} 1 [zgy@Web ~]$ unset value [zgy@Web ~]$ echo ${value:?"not defined"} -bash: value: not defined
提示:用于捕捉由于未定义而导致的错误,如:"not defined"。
(4)${var:+word}
[zgy@Web ~]$ r=${value:+1} [zgy@Web ~]$ echo $r [zgy@Web ~]$ value=oldboy [zgy@Web ~]$ echo $r [zgy@Web ~]$ r=${value:+1} [zgy@Web ~]$ echo $r 1
提示:此功能可用于测试变量是否存在。
(5){value:-word}去掉冒号
[zgy@Web ~]$ httpd=${HTTPD-/usr/sbin/httpd} [zgy@Web ~]$ pidfile=${PIDFILE-/var/run/httpd,pid} [zgy@Web ~]$ echo $httpd $pidfile /usr/sbin/httpd /var/run/httpd,pid [zgy@Web ~]$ echo $HTTPD $PIDFILE
结论:变量没定义就用-号后面的替代
(6)应用例子:/etc/init.d/httpd(注意红色部分)
apachectl=/usr/sbin/apachectl httpd=${HTTPD-/usr/sbin/httpd} prog=httpd pidfile=${PIDFILE-/var/run/httpd/httpd.pid} lockfile=${LOCKFILE-/var/lock/subsys/httpd} RETVAL=0
提示:用yum安装的httpd
系统服务crond脚本使用案例:/etc/init.d/crond
如图:
(2)${value:=word}
与前者类似,只是若变量未定义或者值为空时,在返回word的值的同时将word赋值给value
[root@Web ~]# OLD=${value:=word} [root@Web ~]# echo $OLD word [root@Web ~]# echo $value word [root@Web ~]# value="test" [root@Web ~]# OLD=${value:=word} [root@Web ~]# echo $OLD test [root@Web ~]# echo $value test
注:变量替换的值也可以是``括起来的命令:$USERDIR={$Mydir:-`pwd`}
(3)${value:?message}
若变量以赋值的话,正常替换。否则将消息message送到标准错误输出(若此替换出现在shell程序中,那么该程序将中止运行)
生产应用场景:
1)/etc/init.d/httpd
2)/etc/init.d/crond
3)对变量的路径进行操作,最好先判断路径是否为空。特别是删除操作,容易有危险。
[root@Web ~]#sed -i ‘1d’d.sh [root@Web ~]# cat d.sh path=/server/backup find ${path:=/tmp/} -name “*.tar.gz” -type f | xargs rm -f [root@Web ~]#sh -x d.sh
变量的处理计算变量长度与其他不同方法的耗时对比:
[root@Web ~]# chars=`seq -s " " 100` [root@Web ~]# echo $chars 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 [root@Web ~]# echo ${#chars} 291 [root@Web ~]# echo $chars|wc -m 292 [root@Web ~]# echo $(expr length "$chars") 291 [root@Web ~]# time for i in $(seq 11111);do count=${#chars};done; real 0m0.671s user 0m0.950s sys 0m0.002s [root@Web ~]# time for i in $(seq 11111);do count=`echo ${chars}|wc -m`;done; real 0m27.419s user 0m1.021s sys 0m4.189s [root@Web ~]# time for i in $(seq 11111);do count=`echo expr length "${chars}"`;done; real 0m6.513s user 0m0.346s sys 0m1.376s
我们看到速度相差几十到上百倍,一般情况调用外部命令处理,与内置功能操作性能相差较大。在shell编程中,我们应尽量用内置操作或函数完成。
补充
当然,除了以上操作,Shell还有许多字符串操作,下面小编为大家整理了一些,需要的可以参考一下
字符串的拼接
str1=www
str2=bilibili
string1=$str1$str2 #中间不加别的,直接放一起
string2="$str1 $str2" #双引号括住,中间可加任意字串
string3=$str1"..."$str2 #整体不加引号,若中间要出现别的字串需前后紧挨,且字串双引号括住
string4="${str1}.${str2}.com" #也可以使用${}方式引用变量
echo $string1
echo $string2
echo $string3
echo $string4
运行结果:
wwwbilibili
www bilibili
www...bilibili
www.bilibili.com
读取字符串
$ echo ${abc-'ok'}
ok
$ echo $abc
$ echo ${abc='ok'}
ok
$ echo $abc
ok
$ var1=11;var2=12;var3=
$ echo ${!v@}
var1 var2 var
$ echo ${!v*}
var1 var2 var3
字符串比较
[[ "a.txt" == a* ]] #逻辑真(pattern matching)
[[ "a.txt" =~ .*\.txt ]] #逻辑真(regex matching)
[[ "abc" == "abc" ]] #逻辑真(string comparision)
[[ "11" < "2" ]] #逻辑真(string comparision),按 ascii 值比较