You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Shell脚本匹配replace.txt删除.htaccess中RewriteRule的sed正则问题

.htaccess指定RewriteRule行批量删除脚本问题修复

问题背景

在清理大型.htaccess文件的冗余RewriteRule规则时,原有脚本设计逻辑为:逐行遍历.htaccess内容,匹配replace.txt中存储的待删除规则,命中则删除对应行。测试阶段已将正式.htaccess复制为test.txt作为测试对象,但脚本执行时sed正则匹配报错,无法正确处理RewriteRule行中包含的特殊字符,多次调整正则写法均未解决问题。
原有脚本代码如下:

real_htaccess_file=$(cat $file_path/.htaccess)
test_htaccess_file=$(cat $file_path/test.txt)
replace_rules_file=$(cat $file_path/replace.txt)

# 遍历test_htaccess文件的每一行
while read -r line; do
    # 判断当前行是否包含RewriteRule
    if [[ $line == *"RewriteRule"* ]]; then
        # 遍历replace_rules_file的每一行
        while read -r replace_line; do
            # 判断.htaccess行是否和待删除规则匹配
            if [[ $line == $replace_line ]]; then
                  # 打印命中的行日志
                  echo -e 'Found RewriteRule: '$line

                  # 从test_htaccess_file中删除该行
                  sed -i "/$line/d" $file_path/test.txt
                
            fi
        done < $file_path/replace.txt
    fi
done < $file_path/test.txt

脚本运行输出截图:
脚本运行输出截图

核心报错原因

  • 直接将读取到的RewriteRule原文作为sed匹配pattern传入,但RewriteRule本身包含.、*、?、/、[]、()等大量正则特殊字符,sed默认会将这些字符解析为正则语法而非普通文本,直接传入会导致正则语法错误、匹配结果不符合预期
  • 遍历文件的同时调用sed -i直接修改正在读取的源文件,遍历过程中文件内容变更会导致行指针错位,容易出现漏删、错删
  • 脚本开头全量读取三个文件内容赋值给变量的操作没有实际作用,大文件场景下会占用不必要的内存
  • 变量引用未加双引号,路径或规则包含空格时会出现执行错误

推荐解决方案

优先使用awk实现整行精确匹配,无需手动转义特殊字符,仅需两次文件遍历即可完成全部匹配删除操作,性能远高于循环调用sed,也不会出现读写文件冲突问题。
操作前先备份测试文件:

cp "$file_path/test.txt" "$file_path/test.txt.bak"

替换原有逻辑为以下代码:

#!/bin/bash
# 按需修改为你的文件存放路径
file_path="/path/to/your/htaccess/dir"

# 执行删除:读取replace.txt中所有待删除的RewriteRule,整行匹配删除test.txt中对应行
awk '
NR==FNR {
    if ($0 ~ /RewriteRule/) {
        del_rules[$0] = 1
    }
    next
}
{
    if (!del_rules[$0]) {
        print $0
    } else {
        print "Found and deleted RewriteRule: " $0 > "/dev/stderr"
    }
}
' "$file_path/replace.txt" "$file_path/test.txt" > "$file_path/test.txt.tmp"

# 临时文件替换原文件
mv "$file_path/test.txt.tmp" "$file_path/test.txt"

如果需要保留原有循环+sed的写法,需要先对传入sed的匹配字符串做特殊字符转义,同时避免遍历过程中修改源文件,参考代码如下:

#!/bin/bash
file_path="/path/to/your/htaccess/dir"
cp "$file_path/test.txt" "$file_path/test.txt.bak"

# 定义sed匹配串转义函数,转义所有正则特殊字符
sed_escape() {
    printf '%s\n' "$1" | sed 's/[][\/.$*?^()|+]/\\&/g'
}

# 先把所有待删除规则读入内存
declare -a to_del_rules=()
while read -r replace_line; do
    if [[ $replace_line == *"RewriteRule"* ]]; then
        to_del_rules+=("$replace_line")
    fi
done < "$file_path/replace.txt"

# 遍历待删除规则执行sed删除
for rule in "${to_del_rules[@]}"; do
    echo "Found RewriteRule: $rule"
    escaped_rule=$(sed_escape "$rule")
    sed -i "/^${escaped_rule}$/d" "$file_path/test.txt"
done

注意事项

  • 匹配规则时建议加^(行首锚定)和$(行尾锚定),避免误删部分内容重合的其他规则
  • 所有变量引用统一加双引号,兼容包含空格、特殊字符的路径和规则内容
  • 正式操作.htaccess前务必备份原文件,删除规则后验证站点重写逻辑正常

内容的提问来源于stack exchange,提问作者Dalton Sutton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 07:01:59