目录

shell 字符串详解

Bash Shell 字符串操作详解

Bash 中的字符串操作是脚本编写的核心技能之一,涵盖定义、拼接、截取、替换、匹配等场景。以下是常见用法及示例:


1. 字符串基础

1.1 定义字符串
1
2
3
str1="Hello World"    # 双引号(允许变量替换和转义)
str2='Hello $USER'    # 单引号(原样输出,不解析变量)
str3=$'Line1\nLine2'  # ANSI-C 引号(支持转义字符)
1.2 字符串拼接
1
2
3
4
5
6
name="Alice"
greet="Hello, "$name"!"  # 直接拼接
echo $greet              # 输出: Hello, Alice!

# 使用双引号简化
greet="Hello, ${name}!"  # 推荐写法
1.3 获取字符串长度
1
2
str="abcdefg"
echo ${#str}  # 输出: 7

2. 字符串截取

2.1 按位置截取
语法 描述 示例(str=“abcdef”)
${str:start} start 开始截取到末尾 ${str:2} → “cdef”
${str:start:length} start 截取 length 长度 ${str:1:3} → “bcd”
2.2 按模式截取
语法 描述 示例(str=“app_log_20231010.txt”)
${str#pattern} 删除开头匹配的最短模式 ${str#*_} → “log_20231010.txt”
${str##pattern} 删除开头匹配的最长模式 ${str##*_} → “20231010.txt”
${str%pattern} 删除结尾匹配的最短模式 ${str%.*} → “app_log_20231010”
${str%%pattern} 删除结尾匹配的最长模式 ${str%%.*} → “app_log”

3. 字符串替换

3.1 简单替换
语法 描述 示例(str=“hello world hello”)
${str/old/new} 替换第一个匹配项 ${str/hello/Hi} → “Hi world hello”
${str//old/new} 替换所有匹配项 ${str//hello/Hi} → “Hi world Hi”
3.2 前缀/后缀替换
语法 描述 示例(str=“error.log”)
${str/#prefix/new} 替换开头的 prefix ${str/#error/access} → “access.log”
${str/%suffix/new} 替换结尾的 suffix ${str/%.log/.txt} → “error.txt”

4. 字符串查找

4.1 查找子字符串位置
1
2
3
str="abcdefg"
index=$(expr index "$str" "cde")  # 查找子串起始位置
echo $index  # 输出: 3(位置从1开始计数)
4.2 检查是否包含子串
1
2
3
4
str="hello world"
if [[ $str == *"world"* ]]; then
    echo "包含 'world'"
fi

5. 字符串分割为数组

1
2
3
csv="apple,banana,orange"
IFS=',' read -ra arr <<< "$csv"  # 按逗号分割
echo "${arr[1]}"  # 输出: banana

6. 字符串比较

操作符 描述 示例
=== 相等 [[ "abc" == "abc" ]] → true
!= 不相等 [[ "abc" != "def" ]] → true
>< 按字典序比较 [[ "apple" < "banana" ]] → true
-z 字符串为空 [[ -z "" ]] → true
-n 字符串非空 [[ -n "abc" ]] → true

7. 正则表达式匹配

7.1 使用 =~ 操作符
1
2
3
4
email="user@example.com"
if [[ $email =~ ^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$ ]]; then
    echo "有效邮箱地址"
fi
7.2 提取匹配组
1
2
3
4
str="Date: 2023-10-10"
if [[ $str =~ ([0-9]{4}-[0-9]{2}-[0-9]{2}) ]]; then
    echo "日期: ${BASH_REMATCH[1]}"  # 输出: 日期: 2023-10-10
fi

8. 高级技巧

8.1 处理带空格的字符串
1
2
3
4
5
6
7
8
9
file_path="/path/with spaces/file.txt"
# 双引号保护空格
cp "$file_path" /backup/  

# 数组存储带空格字符串
files=("file1.txt" "file two.txt")
for file in "${files[@]}"; do
    echo "$file"
done
8.2 使用 heredoc 定义多行字符串
1
2
3
4
5
cat <<EOF
第一行
第二行
变量替换: $USER
EOF
8.3 颜色和格式输出
1
2
3
RED='\033[0;31m'
NC='\033[0m'  # 重置颜色
echo -e "${RED}错误信息${NC}"

9. 实用示例

9.1 获取文件名和扩展名
1
2
3
file="image.jpg"
filename="${file%.*}"  # image
extension="${file##*.}"  # jpg
9.2 路径处理
1
2
3
path="/var/log/app.log"
dirname="${path%/*}"   # /var/log
basename="${path##*/}"  # app.log

总结

  • 核心操作:截取 (${var:start:len})、替换 (${var/old/new})、模式删除 (${var#pattern})
  • 关键技巧
    • 使用 [[ ]] 进行字符串比较和正则匹配
    • 用双引号保护含空格的字符串
    • 灵活使用 IFS 分割字符串为数组
  • 注意
    • Bash 字符串索引从 0 开始,但 ${str:start}start 从 0 开始
    • 避免在 [ ] 中使用 ==(推荐用 [[ ]]