目录
1、定义
1.1、双引号
1.2、单引号
1.3、无引号
2、基本操作
2.1、字符串长度
2.2、字符串截取
2.2.1、offset ≥ 0
2.2.2、offset < 0
2.3、字符串匹配
2.3.1、比较
2.3.2、通配符
2.3.2.1、通配符 *
2.3.2.2、通配符 ?
2.3.2.3、通配符 []
2.3.3、正则
2.3.3.1、点号 .
2.3.3.2、星号 *
2.3.3.3、加号 +
2.3.3.4、问号 ?
2.3.3.5、大括号 {}
2.3.3.6、方括号 []
2.3.3.7、转义字符 \
2.4、字符串替换
2.4.1、bash内置的字符串替换
2.4.2、sed命令替换
2.4.3、awk命令替换
2.5、字符串拼接
2.5.1、简单拼接
2.5.2、双引号拼接
2.6、字符串去空格
2.6.1、tr命令去除空格
2.6.2、sed命令去除空格
2.6.3、awk命令去除空格
本文内容同微信公众号【凡登】,关注不迷路,学习上高速,欢迎关注共同学习。
在我们熟知语言中都有自己的数据类型,那么shell是数据类型有哪些?shell属于弱类型语言,它不会强制你声明变量的数据类型。当给一个变量赋值时,根据赋值的内容自动确定数据类型。虽然不能直接定义数据类型,但是我们可以通过一些方法来判断变量的值是否符合某种类型的预期。常见的类型有:字符串、数值、数组、关联数组(map)、日期、布尔、空值。本文主要介绍字符串。
在介绍类型前,先回顾下declare命令. 它可以指定变量的属性,通过-p参数显示每个变量的属性和值,
格式如下:
declare [-aAfFgilrtux] [-p] [name[=value]]
这里仅简单介绍与本文相关的属性:
其他相关参数细节参见《Shell变量定义与基本操作》
本节介绍3中定义字符串方式以及区别:双引号、单引号、无引号。
# 通过declate -p命令查看变量属性
[root@ ~]# s1="a" ; declare -p s1
declare -- s1="a"
[root@ ~]# s2='b' ; declare -p s2
declare -- s2="b"
需要注意,单引号中的字符不会被转义,保持原样输出,参见《条件测试操作符》
单引号和双引号区别
[root@ ~]# s11="a-$s1" ; echo $s11
a-a
[root@ ~]# s22='b-$s2' ; echo $s22
b-$s2
# 无引号,直接赋值
[root@ ~]# s3=c ; declare -p s3
declare -- s3="c"
主要介绍字符串常见的操作:字符串长度、字符串截取、字符串匹配、字符串替换、字符串拼接、字符串去空格
格式:${#字符串} 或 ${#字符串[0]}
[root@ ~]# s1="abcdef"
[root@ ~]# echo "s1_len:${#s1}"
[root@ ~]# echo "s1_len:${#s1[0]}"
s1_len:6
s1_len:6
格式:${字符串: offset:len}
offset: 截取下标位置,索引下标起始从0开始。注:offset前空格。
len: 截取多少个字符,省略则截取offset后所有字符串。
从字符串起始位置右偏移量的位置开始向右截取len字符,offset前空格可省略
# 从第2个字符开始截取3个字符
[root@ ~]# s1="abcdef" ; s2=${s1:1:3}
[root@ ~]# echo "s1:$s1" ; echo "s2:$s2"
s1:abcdef
s2:bcd
# len省略,从第3个字符开始截取
[root@ ~]# s1="abcdef" ; s2=${s1:2}
[root@ ~]# echo "s1:$s1" ; echo "s2:$s2"
s1:abcdef
s2:cdef
# 从前往后接入,有空格
[root@ ~]# s1="abcdef" ; s2=${s1: 3:2}
[root@ ~]# echo "s1:$s1" ; echo "s2:$s2"
s1:abcdef
s2:de
# 从前往后接入,无空格
[root@ ~]# s1="abcdef" ; s2=${s1:3:2}
[root@ ~]# echo "s1:$s1" ; echo "s2:$s2"
s1:abcdef
s2:de
从字符串末尾开始左偏移量的位置开始向右截取len字符,表达式offset前空格必须存在,否则截取失败。
# 从字符串末尾开始向左偏移3的位置,开始向右截取2个字符长度
[root@ ~]# s1="abcdef" ; s2=${s1: -3:2}
[root@ ~]# echo "s1:$s1" ; echo "s2:$s2"
s1:abcdef
s2:de
# 从字符串末尾开始向左偏移4的位置,开始向右截取2个字符长度
[root@ ~]# s1="abcdef" ; s2=${s1: -4:2}
[root@ ~]# echo "s1:$s1" ; echo "s2:$s2"
s1:abcdef
s2:cd
# len为空,截取全部
[root@ ~]# s1="abcdef" ; s2=${s1: -4}
[root@ ~]# echo "s1:$s1" ; echo "s2:$s2"
s1:abcdef
s2:cdef
# 向后截取,无空格,截取失败
[root@ ~]# s1="abcdef" ; s2=${s1:-3:2}
[root@ ~]# echo "s1:$s1" ; echo "s2:$s2"
s1:abcdef
s2:abcdef
使用比较操作符中的"等于"匹配字符串,适合全匹配场景。
字符串其他的比较操作符参见《基本运算符》中【字符串运算符】小节
s1="abc" s2="abc" s3="ABC"
# 匹配
if [ "$s1" = "$s2" ]; then
echo "yes" # 输出:yes
else
echo "no"
fi
# 不支持大小写匹配
if [ "$s1" = "$s3" ]; then
echo "yes"
else
echo "no" # 输出:no
fi
使用通配符进行模式匹配,常见的通配符有 * ? [ ]
注意示例演示使用的 [[ ]] 运算符
匹配任意数量的任意字符
s=abcdef
# 匹配多个字符
if [[ $s == *"cdef" ]] ; then
echo "yes" # 输出:yes
else
echo "no"
fi
# 匹配空字符
if [[ $s == *"cdef"* ]] ; then
echo "yes" # 输出:yes
else
echo "no"
fi
匹配单个字符
s=abcdef
# 匹配一个字符
if [[ $s == ?"bcdef" ]] ; then
echo "yes" # 输出:yes
else
echo "no"
fi
# 不支持匹配空字符
if [[ $s == ?"bcdef"? ]] ; then
echo "yes"
else
echo "no" # 输出:no
fi
# 不支持匹配多个字符
if [[ $s == ?"cdef" ]] ; then
echo "yes"
else
echo "no" # 输出:no
fi
指定字符集,注意大小写
s=abcdef
if [[ $s == [abc]"bcdef" ]] ; then
echo "yes" # 输出:yes
else
echo "no"
fi
s=abcdef
if [[ $s == [a-b]"bcdef" ]] ; then
echo "yes" # 输出:yes
else
echo "no"
fi
s=abcdef
if [[ $s == [^b]"bcdef" ]] ; then
echo "yes" # 输出:yes
else
echo "no"
fi
在Shell脚本中,可以使用grep命令进行正则表达式匹配字符串,
一些常见的正则表达式元字符:
grep命令参数:
如:加号+ 问号? 大括号{} 转义字符 \
匹配任意单个字符
s=abcdef
# 匹配任意一个字符,待匹配字符:'c'
if echo $s | grep -q "ab.def" ; then
echo "yes" # 输出:yes
else
echo "no"
fi
# 不支持匹配任意多个字符, 待匹配字符:'cd'
if echo $s | grep -q "ab.ef" ; then
echo "yes"
else
echo "no" # 输出:no
fi
匹配前面的字符0次或多次。
s="abbbc"
# 匹配0次
if echo $s | grep -q "abbb*c" ; then
echo "yes" # 输出:yes
else
echo "no"
fi
# 匹配多次
if echo $s | grep -q "ab*c" ; then
echo "yes" # 输出:yes
else
echo "no"
fi
# 列举当前目录以.sh结尾的文件
[root@ ~]# ls *.sh
a.sh abc.sh 1.sh
匹配前面的字符1次或多次。
注grep命令不支持+, 使用-E参数扩展正则表达式语法
s="abbcccd"
# 匹1次
if echo $s | grep -qE "abbccc+d" ; then
echo "yes" # 输出:yes
else
echo "no"
fi
# 匹配2次
if echo $s | grep -qE "abbcc+d" ; then
echo "yes" # 输出:yes
else
echo "no"
fi
匹配前面的字符0次或1次。
注grep命令不支持?, 使用-E参数扩展正则表达式语法
s="abbcccd"
# 当?不匹配时候,abbcccc?d => abbcccd 匹配成功
# 当?匹配1次时候,abbcccc?d => abbccccd 匹配失败
if echo $s | grep -qE "abbcccc?d" ; then
echo "yes" # 输出:yes
else
echo "no"
fi
# 当?不匹配时候,abbccc?d => abbccd 匹配失败
# 当?匹配1次时候,abbccc?d => abbcccd 匹配成功
if echo $s | grep -qE "abbccc?d" ; then
echo "yes" # 输出:yes
else
echo "no"
fi
# 列举任意一个字符后缀为.sh文件
[root@ ~]# ls ?.sh
1.sh s.sh t.sh x.sh
匹配字符重复次数范围。
注grep命令不支持{}, 使用-E参数扩展正则表达式语法
s="abbcccd"
# abbc{1,2} => 匹配子串 abbc 或 abbcc 有匹配成功项
if echo $s | grep -qE "abbc{1,2}" ; then
echo "yes" # 输出:yes
else
echo "no"
fi
# abbc{1,2}d => 匹配子串abbcd 或 abbccd, 匹配不成功
if echo $s | grep -qE "abbc{1,2}d" ; then
echo "yes"
else
echo "no" # 输出:no
fi
匹配指定字符集
s="abcdef"
if echo $s | grep -q "[b]cdef" ; then
echo "yes" # 输出:yes
else
echo "no"
fi
# 结合指定字符集[]和指定重复次数{}演示,
# 注,因重复次数{}grep不支持,需要加-E参数扩展
if echo $s | grep -qE "[a-z]{3}ef" ; then
echo "yes" # 输出:yes
else
echo "no"
fi
匹配转义后的特殊字符。
注grep命令不支持\, 使用-E参数扩展正则表达式语法
s="ab?c"
if echo $s | grep -qE "ab\?c" ; then
echo "yes" # 输出:yes
else
echo "no"
fi
if echo $s | grep -qE "ab?c" ; then
echo "yes"
else
echo "no" # 输出:no
fi
[root@ ~]# s0="abcdef" old="bcd" new="BCD"
[root@ ~]# s1=${s0/$old/$new}
[root@ ~]# echo $1
aBCDef
[root@ ~]# echo "abcdef" | sed 's/bcd/BCD/'
aBCDef
[root@ ~]# echo "abcdef" | awk '{gsub("bcd", "BCD"); print}'
aBCDef
[root@ ~]# s0="abc" s1="def" s2=$s0$s1
[root@ ~]# echo "$s2"
abcdef
[root@ ~]# s0="abc" s1="def" s2="$s0$s1"
[root@ ~]# echo "$s2"
abcdef
[root@ ~]# s0=" ab cd ef gh "
[root@ ~]# s1=$(echo "$s0" | tr -d ' ')
# 加 [] 为了方便看字符串前后空格已去
[root@ ~]# echo "[$s1]"
[abcdefgh]
[root@ ~]# s0=" ab cd ef gh "
[root@ ~]# s1=$(echo "$s0" | sed 's/ //g')
# 加 [] 为了方便看字符串前后空格已去
[root@ ~]# echo "[$s1]"
[abcdefgh]
[root@ ~]# s0=" ab cd ef gh "
[root@ ~]# s1=$(echo "$s0" | awk '{gsub(" ", ""); print}')
# 加 [] 为了方便看字符串前后空格已去
[root@ ~]# echo "[$s1]"
[abcdefgh]
以上就是本节全部内容,重点介绍了字符串常见的基本操作,如获取长度,截取、匹配、替换、拼接、去空格。在阅读完后,建议实操练习下,熟练掌握方能在工作中游刃有余。
再次感谢您的阅读,欢迎关注微信公众号【凡登】共同学习。