目录
字符串 String
字符串定义
单引号字符串
双引号字符串
反引号字符串
字符串拼接
字符串长度
字符串比较
==与-eq的区别
子字符串
字符串切片
“切片步长”
遍历字符串
翻转字符串
用反向遍历来实现
调用外部命令rev实现
替换与删除字符
替换字符
删除字符
调用外部命令sed实现
删除空格
遍历字符串数组
c风格for循环
for...in循环
while循环
在计算机编程中,字符串(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比较会报错的。
#!/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 == *"$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:$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
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 命令来实现替换或删除:
#!/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
除了[[: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]
#!/bin/bash
array=("apple" "banana" "cherry")
for ((i=0; i<${#array[@]}; i++))
do
echo "${array[i]}"
done
输出:
apple
banana
cherry
#!/bin/bash
array=("apple" "banana" "cherry")
for item in "${array[@]}"
do
echo "$item"
done
输出:
apple
banana
cherry
#!/bin/bash
array=("apple" "banana" "cherry")
while [ ${#array[@]} -gt 0 ]
do
echo "${array[0]}"
array=("${array[@]:1}")
done
echo "此时数组为空【${array[@]}】"
输出:
apple
banana
cherry
此时数组为空【】
完