字符串替换操作符ai详解

一、替换操作符速查表

操作符名称作用示例结果
${var/old/new}替换第一个替换第一次出现的oldstr="a b a"; echo ${str/a/x}x b a
${var//old/new}全局替换替换所有出现的oldstr="a b a"; echo ${str//a/x}x b x
${var/#old/new}替换开头替换开头的oldstr="abc"; echo ${str/#a/x}xbc
${var/%old/new}替换结尾替换结尾的oldstr="abc"; echo ${str/%c/x}abx

二、详细示例

2.1 ${var/old/new} – 替换第一个匹配

#!/bin/bash
# 只替换第一次出现的

text="apple banana apple orange apple"
echo "${text/apple/pear}"
# 输出: pear banana apple orange apple
#       ^^^^ 只替换了第一个

# 实际应用
filename="image-2024-01-15.jpg"
newfile="${filename/-/_}"  # 第一个-换成_
echo "$newfile"  # image_2024-01-15.jpg

2.2 ${var//old/new} – 全局替换

#!/bin/bash
# 替换所有匹配

text="apple banana apple orange apple"
echo "${text//apple/pear}"
# 输出: pear banana pear orange pear
#       ^^^^     ^^^^     ^^^^ 全部替换

# 实际应用
sentence="Hello World, Hello Linux, Hello Shell"
echo "${sentence//Hello/Hi}"
# 输出: Hi World, Hi Linux, Hi Shell

# 替换空格
csv="a b c d"
echo "${csv// /,}"  # a,b,c,d

2.3 ${var/#old/new} – 替换开头匹配

#!/bin/bash
# 只有开头匹配时才替换

text="abc123"
echo "${text/#abc/xyz}"   # 输出: xyz123(开头匹配)
echo "${text/#123/xyz}"   # 输出: abc123(开头不匹配,不变)

# 实际应用
url="https://example.com"
echo "${url/#http:/https:}"  # https://example.com

# 添加前缀
path="file.txt"
echo "${path/#/data/}"  # data/file.txt(在开头添加)

2.4 ${var/%old/new} – 替换结尾匹配

#!/bin/bash
# 只有结尾匹配时才替换

text="123abc"
echo "${text/%abc/xyz}"   # 输出: 123xyz(结尾匹配)
echo "${text/%123/xyz}"   # 输出: 123abc(结尾不匹配,不变)

# 实际应用
filename="image.jpg"
echo "${filename/%.jpg/.png}"  # image.png

# 修改扩展名
for file in *.txt; do
    newname="${file/%.txt/.bak}"
    mv "$file" "$newname"
done

三、综合应用示例

3.1 文件批量重命名

#!/bin/bash
# rename.sh

# 将所有.jpg改为.png
for file in *.jpg; do
    newname="${file/%.jpg/.png}"
    echo "重命名: $file -> $newname"
    # mv "$file" "$newname"
done

# 添加前缀
for file in *.txt; do
    newname="backup_$file"
    # 或用替换
    # newname="${file/#/backup_}"
    echo "新文件名: $newname"
done

# 替换文件名中的空格
for file in *\ *; do
    newname="${file// /_}"
    mv "$file" "$newname"
done

3.2 文本处理

#!/bin/bash
# text_process.sh

text="Hello World, Hello Shell, Hello World"

# 1. 基本替换
echo "原始: $text"
echo "替换第一个World: ${text/World/Linux}"
echo "替换所有World: ${text//World/Linux}"
echo "替换开头Hello: ${text/#Hello/Hi}"
echo "替换结尾World: ${text/%World/Everyone}"

# 2. 变量替换
name="John Doe"
echo "你好, ${name/ /, }"  # 你好, John, Doe

# 3. 路径处理
path="/home/user/docs/file.txt"
echo "目录: ${path%/*}"           # /home/user/docs
echo "文件名: ${path##*/}"        # file.txt
echo "基础名: ${filename%.*}"      # file
echo "扩展名: ${filename##*.}"     # txt

3.3 数据格式化

#!/bin/bash
# format.sh

# 1. 日期格式化
date="2024-02-20"
echo "美式: ${date//-//}"          # 2024/02/20
echo "日式: ${date//-//}"          # 2024/02/20
echo "无分隔符: ${date//-/}"       # 20240220

# 2. CSV转置
csv="a,b,c,d"
echo "CSV转空格: ${csv//,/ }"      # a b c d
echo "CSV转竖线: ${csv//,/|}"      # a|b|c|d

# 3. URL参数处理
query="name=John&age=25&city=NYC"
echo "${query//&/\\n}"  # 每行一个参数
# name=John
# age=25
# city=NYC

# 4. 手机号格式化
phone="13800138000"
echo "${phone:0:3}-${phone:3:4}-${phone:7:4}"
# 138-0013-8000

3.4 配置文件处理

#!/bin/bash
# config.sh

# 读取配置文件
while IFS='=' read key value; do
    # 去掉前后空格
    key="${key// /}"
    value="${value// /}"

    # 替换变量引用
    if [[ $value == *\${*}* ]]; then
        var_name="${value#\${}"
        var_name="${var_name%\}}"
        value="${!var_name}"
    fi

    declare "$key=$value"
done < config.txt

# 模板替换
template="Hello ${name}, your home is ${home}"
content="${template//\$\{name\}/$name}"
content="${content//\$\{home\}/$home}"
echo "$content"

四、组合操作

#!/bin/bash
# complex.sh

text="Hello World, Hello Shell"

# 1. 多次替换
step1="${text//Hello/Hi}"
step2="${step1/World/Linux}"
echo "$step2"  # Hi Linux, Hi Shell

# 2. 链式操作(一行)
result="${text//Hello/Hi}"
result="${result/World/Linux}"
echo "$result"

# 3. 条件替换
if [[ $text == *World* ]]; then
    text="${text/World/Linux}"
fi

# 4. 变量默认值+替换
name="${1:-Guest}"
name="${name// /_}"
echo "Welcome, $name"

五、实际应用场景

5.1 日志分析

#!/bin/bash
# log_parser.sh

log="2024-02-20 10:30:25 ERROR: Connection failed"

# 提取时间
time="${log:11:8}"
echo "时间: $time"

# 提取级别
level="${log#* }"
level="${level%%:*}"
echo "级别: $level"

# 提取消息
msg="${log#*: }"
echo "消息: $msg"

# 格式化输出
formatted="${log/ / | }"
formatted="${formatted/:/ | }"
echo "$formatted"
# 2024-02-20 | 10:30:25 | ERROR | Connection failed

5.2 模板引擎

#!/bin/bash
# template.sh

name="张三"
age=25
city="北京"

template='姓名: ${name}, 年龄: ${age}, 城市: ${city}'

# 替换所有变量
result="$template"
result="${result//\$\{name\}/$name}"
result="${result//\$\{age\}/$age}"
result="${result//\$\{city\}/$city}"

echo "$result"
# 输出: 姓名: 张三, 年龄: 25, 城市: 北京

六、总结对比

操作符作用范围记忆口诀常用场景
${var/old/new}第一个一个斜杠替换第一个
${var//old/new}全部两个斜杠全部替换
${var/#old/new}开头# 开头加前缀、改开头
${var/%old/new}结尾% 结尾改扩展名、加后缀

规则很简单

  • / 一个斜杠 = 第一个
  • // 两个斜杠 = 全部
  • /# 井号开头 = 匹配开头
  • /% 百分号 = 匹配结尾

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注