字符串 String
在计算机编程中,字符串(String)是一种基本的数据类型,它表示文本或字符序列。在各种编程语言中,字符串都扮演着重要的角色,而在shell脚本中也不例外。在Shell脚本中,字符串的使用非常广泛,可以用于处理文本、文件名、命令参数等等。
字符串定义
在shell中,字符串可以用单引号、双引号或反引号来定义。
单引号字符串
单引号字符串中的内容将原样输出,不会进行任何变量替换。例如:
#!/bin/bash str='abcd' echo '$str' DATE=$(date) echo '$DATE'
输出:
$str
$DATE
双引号字符串
双引号字符串中的内容将进行变量替换。例如:
#!/bin/bash str='abcd' echo "$str" DATE=$(date) echo "$DATE"
输出:
abcd
Thu 24 Aug 2023 12:24:27 AM UTC
【注意】据说有的shell环境两者还区别于它们转义字符的解析,但至少我用的版本没有差别:
#!/bin/bash echo 'Hello\n World!' echo "Hello\n World!" echo -e 'Hello\n World!' echo -e "Hello\n World!"
输出:
Hello\n World!
Hello\n World!
Hello
World!
Hello
World!
反引号字符串
反引号(``,数字1左边的键)字符串用于执行命令并将其输出作为字符串。例如:
#!/bin/bash # 获取当前日期并存储到变量中 current_date=`date` echo "当前日期是:$current_date" result=`ls -l | wc` echo "命令序列的输出是:$result"
输出:
当前日期是:Thu 24 Aug 2023 10:28:54 AM UTC
命令序列的输出是: 3 20 118
字符串拼接
1. 字符串自然的首尾相接在一起
2. 使用字符串拼接运算符: +=
#!/bin/bash str1="Hello" str2="world!" str3="${str1},${str2}" echo $str3 str+=$str1 echo $str str+=$str2 echo $str
输出:
Hello,world!
Hello
Helloworld!
字符串长度
要获取字符串的长度,可以使用${#string}
。例如:
#!/bin/bash str='Hello\nWorld' echo "$str的长度为:"${#str} str="Hello\nWorld" echo "$str的长度为:"${#str} current_date=`date` echo "date命令返回的字串长度为:${#current_date}"
输出:
Hello\nWorld的长度为:12
Hello\nWorld的长度为:12
date命令返回的字串长度为:31
注:同时也印证了我用的linux环境下单、双引号字符串在转义解析方面无区别。
字符串比较
字符串没有大小之分,只能比较是否相等 == 、不相等 !=。
#!/bin/bash str1='Hello' str2='World' if [ "$str1" == "$str2" ]; then echo "Strings are equal" else echo "Strings are not equal" fi
输出:
Strings are not equal
==与-eq的区别
字符串对比通常用 ==,可转数字的字符串也能用 -eq,但不能转数字的用-eq比较会报错的。
#!/bin/bash num1="123" num2="0123" if [ "$num1" -eq "$num2" ]; then echo "Numbers are equal" else echo "Numbers are not equal" fi if [ "$num1" == "$num2" ]; then echo "Numbers are equal" else echo "Numbers are not equal" fi
输出:
Numbers are equal
Numbers are not equal
子字符串
字符串的比较支持通配符 “?”和"*",分别表示可以代替一个和多个字符。
例如,[[string==∗"string == *"substring"*]] 可以判断后者是否为前者的子字符串。
示例:
#!/bin/bash string="Hello World" substring="Hello" if [[ $string == *"$substring"* ]]; then echo "Substring found" else echo "Substring not found" fi if [[ $string == "$substring"* ]]; then echo "String starts with Substring" elif [[ $string == *"$substring" ]]; then echo "String ends with Substring" elif [[ $string == *"$substring"* ]]; then echo "Substring is in the middle of String" else echo "Substring not found" fi
输出:
Substring found
String starts with Substring
字符串切片
格式: ${string: start,length切片长度}
start:切片起始索引位置,索引从0开始。可以理解为切掉字符串前部的字符数。
length:正数为切片长度,即留下的字符个数;如为负数表示切掉字符串尾部的字符数
#!/bin/bash str="Hello,world!" echo ${str:0:5} # 输出 "Hello" echo ${str::5} # 输出 "Hello" echo ${str:1:5} # 输出 "ello," echo ${str:8:5} # 输出 "rld!" echo ${str::-1} # 输出 "Hello,world" echo ${str::-5} # 输出 "Hello,w" echo ${str:3:-3} # 输出 "lo,wor"
输出:
Hello
Hello
ello,
rld!
Hello,world
Hello,w
lo,wor
“切片步长”
shell没有切片步长step的概念,但可以用循环实现,如输出字串奇偶位数的“切片”:
#!/bin/bash string="Hello,world!" result="" index=0 step=2 while [ $index -lt ${#string} ]; do char=${string:$index:1} index=$((index+step)) result+=$char done echo $result result="" index=1 while [ $index -lt ${#string} ]; do char=${string:$index:1} index=$((index+step)) result+=$char done echo $result result="" for ((i=1; i<${#string}; i=i+step)); do char=${string:$i:1} result+=$char done echo $result
输出:
Hlowrd
el,ol!
el,ol!
遍历字符串
使用单个字符的切片 {str:{str:{str:i:1} 循环读取所有字符,例如:
#!/bin/bash str="hello,world" echo $str for (( i=0; i<${#str}; i++ )); do echo -n ${str:$i:1}" " done
输出:
hello,world
h e l l o , w o r l d
翻转字符串
用反向遍历来实现
#!/bin/bash str="hello,world" echo $str # 反向遍历 for (( i=${#str}-1; i>=0; i-- )); do echo -n ${str:$i:1}" " done echo str2="" # 反向拼接 for (( i=${#str}-1; i>=0; i-- )); do str2+=${str:$i:1} done echo $str2
输出:
hello,world
d l r o w , o l l e h
dlrow,olleh
调用外部命令rev实现
hann@HannYang:~$ str="hello,world" hann@HannYang:~$ echo $str hello,world hann@HannYang:~$ echo $str|rev dlrow,olleh hann@HannYang:~$ echo $str hello,world hann@HannYang:~$ str=`echo $str` hann@HannYang:~$ echo $str hello,world hann@HannYang:~$ str=`echo $str|rev` hann@HannYang:~$ echo $str dlrow,olleh
替换与删除字符
替换字符
格式:${string//pattern/replacement}
#!/bin/bash str="hello,world" echo $str echo ${str//world/shell}
输出:
hello,world
hello,shell
删除字符
格式:${string//pattern/}
替换内容replacement为空即删除。
#!/bin/bash str="hello,world" echo $str echo ${str//world/}
输出:
hello,world
hello,
【注意】替换和删除操作都不是原地操作,要改变原字符串,请操作后赋值:
#!/bin/bash str="hello,world" echo $str echo ${str//world/shell} echo ${str//world/} echo echo $str str=${str//world/} echo $str
输出:
hello,world
hello,shell
hello,
hello,world
hello,
调用外部命令sed实现
比如,调用 sed 命令来实现替换或删除:
#!/bin/bash str="hello,world" new_string=$(echo $str | sed 's/world/Shell/g') echo $new_string #直接用反引号字符串表示: echo `echo $str | sed 's/world//g'`
输出:
hello,Shell
hello,
删除空格
#!/bin/bash str=" hello world 1 2 3 4 5 " no_space_str=${str//[[:space:]]/} echo $no_space_str
输出:
helloworld12345
POSIX 标准定义的字符类
除了[[:space:]]表示匹配空格(包括空格、制表符、换页符等),还有以下特殊格式可用:
[[:alnum:]]:匹配字母和数字。
[[:alpha:]]:匹配字母。
[[:digit:]]:匹配数字。
[[:graph:]]:匹配可见字符(非空格和非控制字符)。
[[:lower:]]:匹配小写字母。
[[:upper:]]:匹配大写字母。
[[:punct:]]:匹配标点符号。
[[:print:]]:匹配可打印字符(非控制字符)。
[[:cntrl:]]:匹配控制字符(0x01 到 0x1F 和 0x7F)。
示例:
#!/bin/bash str=" Hello123World 1 2 , 3 4 5" str1=${str//[[:digit:]]/} echo [$str1] str2=${str//[[:upper:]]/} echo [$str2] str3=${str//[[:alnum:]]/} echo [$str3] str4=${str//[[:alpha:]]/} echo [$str4] str5=${str//[[:punct:]]/} echo [$str5]
输出:
[ HelloWorld , ]
[ ello123orld 1 2 , 3 4 5]
[ , ]
[ 123 1 2 , 3 4 5]
[ Hello123World 1 2 3 4 5]
遍历字符串数组
c风格for循环
#!/bin/bash array=("apple" "banana" "cherry") for ((i=0; i<${#array[@]}; i++)) do echo "${array[i]}" done
输出:
apple
banana
cherry
for...in循环
#!/bin/bash array=("apple" "banana" "cherry") for item in "${array[@]}" do echo "$item" done
输出:
apple
banana
cherry
while循环
#!/bin/bash array=("apple" "banana" "cherry") while [ ${#array[@]} -gt 0 ] do echo "${array[0]}" array=("${array[@]:1}") done echo "此时数组为空【${array[@]}】"
输出:
apple
banana
cherry
此时数组为空【】
完