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

如何用sed替换指定注释间内容并每日自动更新(FreeBSD环境)

问题:替换指定注释块间的动态内容

场景说明

我需要按需更新模板文件里CODE1或CODE2注释块之间的内容,同时保留这两个注释行,方便后续Cron每日执行脚本时重复更新。模板文件结构如下:

...
some code
...
// BEGIN CODE1
// END CODE1
...
some code
...
// BEGIN CODE2
// END CODE2
...
some code
...

其中CODE1区域用于动态生成include文件路径,每次Cron运行时都会生成新的路径内容。

尝试过的脚本及报错

我写了如下脚本:

#!/bin/sh

directory="/path/to/list/files"

for file in "$directory"/*.txt
do
  if [ -f "$file" ]; then
    content=$(sed -n '/\/\/ BEGIN CODE1/{:a;N;/\/\/ END CODE1/!ba;p}' "$file")

    sed -i '' '/\/\/ BEGIN/,/\/\/ END/{//!c\
INCLUDE /tmp/test.txt
}' "/root/replace.txt"
  fi
done

运行后出现报错:

sed: 1: "/\/\/ BEGIN/{:a;N;/\/\/ ...": unexpected EOF (pending }'s)

期望输出

CODE1区域更新后需变成:

...
some code
...
// BEGIN CODE1
$INCLUDE "/usr/local/etc/namedb/keys/domain.com/ksk.key"
$INCLUDE "/usr/local/etc/namedb/keys/domain.com/zsk.key"
// END CODE1
...
some code
...
// BEGIN CODE2
// END CODE2
...
some code
...

实际业务场景

通过Cron每日检查$FolderKeys目录,更新/usr/local/etc/namedb/working/domain.com.db文件中// BEGIN DNSSEC CODE与// END DNSSEC CODE之间的内容,要求只替换块内内容、保留注释行,不修改文件其他部分。

动态生成内容的逻辑如下:

FolderKeys="/usr/local/namedb/keys"
FolderSites="/usr/local/etc/namedb/working"
declare -a Sites=( $(ls /$FolderSites | grep '.db$' | sed 's/.db$//') )

for Site in "${Sites[@]}"
do
    ls -la $FolderJail$FolderKeys/$Site/*.key
done

解决方案

1. 修复sed语法错误

你遇到的报错是FreeBSD sed的语法限制导致的:c命令后的换行格式有严格要求,而且模糊的匹配范围(/\/\/ BEGIN/,/\/\/ END/)容易误命中其他注释块。

2. 完整适配脚本

下面是适配FreeBSD环境的脚本,能精准替换指定块内容,同时自动生成动态INCLUDE行:

#!/bin/sh

# 配置参数
FolderKeys="/usr/local/namedb/keys"
FolderSites="/usr/local/etc/namedb/working"
TargetFile="/usr/local/etc/namedb/working/domain.com.db"
# 精准定位目标块的标记
StartMarker="// BEGIN DNSSEC CODE"
EndMarker="// END DNSSEC CODE"
# 若用到FolderJail请补充定义
# FolderJail="/path/to/jail"

# 动态生成要插入的INCLUDE内容
generate_content() {
    for site_db in "$FolderSites"/*.db; do
        site=$(basename "$site_db" .db)
        # 遍历该站点下的所有key文件
        for key_file in "$FolderJail$FolderKeys/$site"/*.key; do
            [ -f "$key_file" ] && echo "\$INCLUDE \"$key_file\""
        done
    done
}

# 生成临时内容文件
TempContent=$(mktemp)
generate_content > "$TempContent"

# 执行sed替换:保留起始/结束标记,替换中间内容
sed -i.bak '' -e "/$StartMarker/{
    p
    r $TempContent
    :a
    N
    /$EndMarker/!ba
    s/.*\n//
}" "$TargetFile"

# 清理临时文件
rm "$TempContent"
# 可选:删除备份文件,不需要则注释此行
# rm "${TargetFile}.bak"

脚本关键逻辑

  • 精准匹配:用StartMarker和EndMarker定位目标块,避免误替换其他注释区域
  • 动态生成:自动遍历站点和key文件,生成符合格式的$INCLUDE行
  • sed替换逻辑:
    1. 匹配到起始标记后先打印该行
    2. 插入临时文件里的动态内容
    3. 循环读取后续行直到匹配到结束标记,清空中间原有内容后打印结束标记
  • 安全备份:-i.bak会自动生成原文件的备份,防止误操作丢失数据

注意事项

  • 确保Cron执行用户对目标文件、key目录有读写权限
  • 测试时可去掉-i.bak参数,直接将输出打印到终端,确认逻辑正确后再执行修改
  • 若FolderJail是必填参数,记得在脚本开头补充定义

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 23:07:53