Shell字符串的用法(非常详细)
Shell 字符串(String)其实是一系列字符的组合(如 abcd)。
在 Shell 脚本编程中,字符串是最常用的数据类型之一,只要不进行数学计算,甚至数字也可以看作字符串。
定义一个字符串可以由单引号
使用双引号
不使用引号引用的字符串中,若出现变量也会被解析,这一点和使用双引号
【实例】3 种字符串定义形式。
【实例】获取字符串长度。
【实例】字符串拼接。
Shell 截取字符串通常有两种方式:
先介绍第一种方式,从指定位置截取字符串。
从指定的位置截取字符串需要满足两个条件:
既然需要指定起始位置,那就涉及计数方向的问题,到底是从字符串左边开始计数,还是从字符串右边开始计数?答案是 Shell 支持两种计数方式。我们既可以从指定的位置往前面截取,也可以从指定的位置向后截取。
1) 从字符串左边开始计数:
2) 从字符串右边开始计数:
【实例】从字符串左边计数进行截取。
从字符串右边计数进行截取:
接下来介绍第二种截取字符串的方式:从指定字符开始截取。
从指定字符开始截取的方式是没办法指定字符串长度的,只能从指定的字符截取到字符串末尾。可以截取指定字符右边的所有字符,也可以截取字符左边的所有字符。
1) 使用“#”截取指定字符右边的所有字符:
2) 使用“%”截取指定字符左边的所有字符:
【实例】使用“#”截取指定字符右边的所有字符(有3种写法)。
上面 3 种写法都是遇到第一个匹配的字符就结束了,我们做个实验匹配 URL 中的斜线,这个 URL 中有三条斜线,看一下结果匹配的是哪条斜线?
截取指定字符左边的所有字符:
我们把以上字符串截取格式做一个汇总,见下表。
在 Shell 脚本编程中,字符串是最常用的数据类型之一,只要不进行数学计算,甚至数字也可以看作字符串。
定义一个字符串可以由单引号
' '
引起来,也可以由双引号" "
引起来,也可以不用引号。但是它们之间是有区别的:
Str1=xiaozhou Str2='xiaozhou' Str3="xiaozhou"使用单引号
' '
的字符串,任何字符都会原样输出,在其中使用变量是无效的。字符串中不能出现单引号,即使对单引号进行转义也不行。使用双引号
" "
的字符串,如果其中包含了某个变量,那么该变量将会被解析(得到该变量的值),而不是将变量名原样输出。字符串中可以出现双引号,只要它被转义了就可以。不使用引号引用的字符串中,若出现变量也会被解析,这一点和使用双引号
" "
引用的字符串一样。但字符串中不能出现空格,否则空格后的字符串会被认为由其他变量或者命令解析。【实例】3 种字符串定义形式。
[root@linux opt]# vim demo6.sh #!/bin/bash num=99 str1=c.biancheng.net$num str2="shell \"script\" $num" str3='C语言中文网:$num' echo $str1 echo $str2 echo $str3 [root@linux opt]# bash demo6.sh c.biancheng.net99 shell "script" 99 C语言中文网:$num从示例中可以看出:
- 变量 str1 中包含了变量 num,它被 Shell 解析了,所以输出的内容中包含变量 num 的值。$num 后有空格,紧随着空格的是变量 str2,这里要注意 Shell 将变量 str2 解释为一个新的变量名而不是作为变量 str1 中字符串的一部分。
- 变量 str2 中包含了双引号,但是被转义了(反斜杠\是转义字符)。同时,str2 变量中也包含了 $num,它也被 Shell 解析了。
- 变量 str3 中也包含 $num,但是仅作为一串普通字符,并没有被 Shell 解析。
Shell获取字符串的长度
在 Shell 脚本中获取字符串的长度,语法格式如下:${#string_name}其中,string_name 表示字符串变量名。
【实例】获取字符串长度。
[root@linux opt]# vim demo7.sh #!/bin/bash str="https://c.biancheng.net/" echo ${#str} [root@linux opt]# bash demo7.sh 24
Shell字符串的拼接
字符串拼接在编写 Shell 脚本时候用得非常多,其过程也非常简单,有多简单呢?在拼接的过程中不需要使用任何运算符号,直接将两个字符串变量并排放在一起就实现拼接了。【实例】字符串拼接。
[root@linux opt]# vim demo8.sh #!/bin/bash name="Shell" url="https://www.c.biancheng.net/" str1=$name$url # 中间不能有空格 str2="$name $url" # 如果用双引号引用,则中间可以有空格 str3=$name":"$url # 中间可以出现别的字符串 str4="$name:$url" # 这样写也可以 str5="${name}Script:${url}index.html" # 需要给变量名加上大括号 echo $str1 echo $str2 echo $str3 echo $str4 echo $str5 [root@linux opt]# bash demo8.sh Shellhttps://www.c.biancheng.net/ Shell https://www.c.biancheng.net/ Shell: https://www.c.biancheng.net/ Shell: https://www.c.biancheng.net/ ShellScript: https://www.c.biancheng.net/index.html在定义变量 str3 时,$name 和 $url 之间之所以不能出现空格,是因为当字符串不用任何一种引号引用时,遇到空格就认为字符串结束了,空格后的内容会被当作其他变量或命令解析。
在定义变量 str5 时,加
{ }
主要是为了帮助 bash 解释器识别变量的边界。
Shell字符串的截取
在编写某些特殊需求的 Shell 脚本时,字符串截取是一种常用且重要的操作。Shell 截取字符串通常有两种方式:
- 从指定位置开始截取,比如从第 13 个字符截取到第 17 个字符;
- 从指定字符开始截取,比如一串字符 abcdef,从字符 a 截取到字符 d。
先介绍第一种方式,从指定位置截取字符串。
从指定的位置截取字符串需要满足两个条件:
- 一是知道从哪个位置开始截;
- 二是截取的长度。
既然需要指定起始位置,那就涉及计数方向的问题,到底是从字符串左边开始计数,还是从字符串右边开始计数?答案是 Shell 支持两种计数方式。我们既可以从指定的位置往前面截取,也可以从指定的位置向后截取。
1) 从字符串左边开始计数:
${string:start:length}其中,string 是要截取的字符串(一般为字符串变量名),start 是起始位置(左边开始,从 0 开始计数);length 是要截取的长度(省略的话表示直到字符串的末尾)。
2) 从字符串右边开始计数:
${string:0-start:length}与上一种方式相比,语句中仅仅多了 0-,这是一种固定的写法,专门用来表示从字符串右边开始计数。
【实例】从字符串左边计数进行截取。
[root@linux opt]# vim demo9.sh #!/bin/bash url=c.biancheng.net echo "写起始位置与截取长度:" ${url:2:9} echo "只写起始位置:" ${url:2} [root@linux opt]# bash demo9.sh 写起始位置与截取长度:biancheng 只写起始位置:biancheng.net
从字符串右边计数进行截取:
[root@linux opt]# vim demo10.sh #!/bin/bash url="c.biancheng.net" echo ${url:0-13:9} echo ${url:0-13} [root@linux opt]# bash demo10.sh iancheng. biancheng.net若选择从字符串右边计数进行截取,需要注意两点:
- 从左边开始计数时,起始数字是 0(符合程序员思维);从右边开始计数时,起始数字是 1(符合常人思维)。计数方向的不同,起始数字也会有所不同。
- 不管从哪边开始计数,截取方向都是从左到右。
接下来介绍第二种截取字符串的方式:从指定字符开始截取。
从指定字符开始截取的方式是没办法指定字符串长度的,只能从指定的字符截取到字符串末尾。可以截取指定字符右边的所有字符,也可以截取字符左边的所有字符。
1) 使用“#”截取指定字符右边的所有字符:
${string#*chars}其中,string 是要截取的字符串(一般为字符串变量名);chars 是指定的字符;*是通配符的一种,表示任意长度的字符串。
这里的 chars 是不会被截取的。
2) 使用“%”截取指定字符左边的所有字符:
${string%chars*}重点注意一下星号(*)的位置,因为要截取 chars 左边的字符而忽略 chars 右边的字符,所以星号应该位于 chars 的右侧。其他用法和“#”相同。
【实例】使用“#”截取指定字符右边的所有字符(有3种写法)。
[root@linux opt]# vim demo11.sh #!/bin/bash url="https://c.biancheng.net/index.html" echo "内容:"$url echo "第一种截取写法" ${url#*t} echo "第二种截取写法" ${url#*ttps} echo "第三种截取写法" ${url#https://} [root@linux opt]# bash demo11.sh 内容:https://c.biancheng.net/index.html 第一种截取写法 tps://c.biancheng.net/index.html 第二种截取写法 ://c.biancheng.net/index.html 第三种截取写法 c.biancheng.net/index.html
- 第一种写法:匹配单个字符并进行截取;
- 第二种写法:匹配一串字符串并进行截取;
- 第三种写法:如果不需要忽略 chars 左边的字符,那么不写星号也是可以的。
上面 3 种写法都是遇到第一个匹配的字符就结束了,我们做个实验匹配 URL 中的斜线,这个 URL 中有三条斜线,看一下结果匹配的是哪条斜线?
[root@linux opt]# vim demo12.sh #!/bin/bash url="https://c.biancheng.net/index.html" echo "内容: "$url echo ${url#*/} [root@linux opt]# bash demo12.sh 内容: https://c.biancheng.net/index.html /c.biancheng.net/index.html通过实验可以看到,使用从指定字符开始截取的方式,匹配到的都是第一个符合条件的元素。如果希望直到最后一个指定字符(子字符串)匹配才结束,可以使用“##”,具体格式为
${string##*chars}【实例】使用“#”和“##”分别进行截取。
[root@linux opt]# vim demo13.sh #!/bin/bash url="https://c.biancheng.net/index.html" echo "内容:"$url echo "使用#截取斜线“/”右边的所有字符:"${url#*/} echo "使用##截取斜线“/”右边的所有字符:"${url##*/} str="---aa+++aa@@@" echo "内容:"$str echo "使用#截取“aa”右边的所有字符:"${str#*aa} echo "使用##截取“aa”右边的所有字符:"${str##*aa} [root@linux opt]# bash demo13.sh #执行此脚本 内容:https://c.biancheng.net/index.html 使用#截取斜线“/”右边的所有字符:/c.biancheng.net/index.html 使用##截取斜线“/”右边的所有字符:index.html 内容:---aa+++aa@@@ 使用#截取“aa”右边的所有字符:+++aa@@@ 使用##截取“aa”右边的所有字符:@@由此可见,使用
${string##*chars}
是直到最后一个符合条件的匹配项才结束,而${string#*chars}
是遇到第一个符合条件的匹配项就结束。截取指定字符左边的所有字符:
[root@linux opt]# vim demo14.sh #!/bin/bash url="https://c.biancheng.net/index.html" echo "内容:"$url echo "使用%截取斜线“/”左边的所有字符:" ${url%/*} echo "使用%%截取斜线“/”左边的所有字符:" ${url%%/*} str="---aa+++aa@@@" echo "内容:"$str echo "使用%截取“aa”左边的所有字符:" ${str%aa*} echo "使用%%截取“aa”左边的所有字符:" ${str%%aa*} [root@linux opt]# bash demo14.sh 内容:https://c.biancheng.net/index.html 使用%截取斜线“/”左边的所有字符:https://c.biancheng.net 使用%%截取斜线“/”左边的所有字符:https: 内容:---aa+++aa@@@ 使用%截取“aa”左边的所有字符:---aa+++ 使用%%截取“aa”左边的所有字符:---
我们把以上字符串截取格式做一个汇总,见下表。
格 式 | 说 明 |
---|---|
${string:start:length} | 从 string 字符串的左边起始位置开始,向右截取 length 个字符 |
${string:start} | 从 string 字符串的左边起始位置开始截取,直到最后 |
${string:0-start:length} | 从 string 字符串的右边起始位置开始,向右截取 length 个字符 |
${string:0-start} | 从 string 字符串的右边起始位置开始截取,直到最后 |
${string#*chars} | 从 string 字符串第一次出现 *chars 的位置开始,截取 *chars 右边的所有字符 |
${string##*chars} | 从 string 字符串最后一次出现 *chars 的位置开始,截取 *chars 右边的所有字符 |
${string%*chars} | 从 string 字符串第一次出现 *chars 的位置开始,截取 *chars 左边的所有字符 |
${string%%*chars} | 从 string 字符串最后一次出现 *chars 的位置开始,截取 *chars 左边的所有字符 |