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

Linux下Makefile中用tree输出替换围栏文本块的sed实现问题

在Makefile中用tree输出替换多行围栏文本块的解决方案

我之前也碰到过类似的需求,在Makefile里处理跨行文本替换确实有点麻烦——毕竟sed默认是单行模式,直接用它匹配带换行的围栏块很容易踩坑。下面给你两种实用的解决方案,分别对应替换整个围栏块和只替换中间占位符的场景:

场景1:替换整个围栏块(从[fencedtitle]到第二个----的全部内容)

如果你的目标是把整个围栏结构(包括标题、分隔线和占位符)直接换成tree的输出,用awk会比sed更直观,因为awk天然支持多行处理逻辑。

在Makefile里添加如下规则:

update-tree-output:
    # 先获取tree的输出,转义特殊字符避免冲突
    TREE_CONTENT=$$(tree | sed 's/\$$/\\$$/g'); \
    # 用awk处理文本替换
    awk -v tree="$$TREE_CONTENT" ' \
        /^\[fencedtitle\]$/ { \
            print tree;  # 输出tree的结果
            skip_mode=1;  # 开启跳过模式
            next; \
        } \
        skip_mode && /----$$/ { \
            skip_mode++; \
            # 遇到第二个----时关闭跳过模式
            if (skip_mode == 3) skip_mode=0; \
            next; \
        } \
        !skip_mode  # 非跳过模式下正常输出原内容
    ' README.md > tmp_tree.md && mv tmp_tree.md README.md

逻辑说明:

  1. 用$$(tree | sed 's/\$$/\\$$/g')获取tree的输出并转义$符号,避免和Makefile的变量语法冲突;
  2. awk通过skip_mode变量控制跳过围栏块的内容:匹配到[fencedtitle]时输出tree结果,然后跳过后续行直到遇到第二个----;
  3. 最后把处理后的内容写入临时文件,再替换原文件(避免直接修改原文件导致意外)。

场景2:保留围栏结构,只替换中间的REPLACEMENT占位符

如果想保留[fencedtitle]和上下的----分隔线,只替换中间的REPLACEMENT文本,只需调整awk的逻辑:

update-tree-placeholder:
    TREE_CONTENT=$$(tree | sed 's/\$$/\\$$/g'); \
    awk -v tree="$$TREE_CONTENT" ' \
        /^\[fencedtitle\]$/ { \
            print;  # 保留原标题行
            skip_mode=1; \
            next; \
        } \
        skip_mode == 1 && /----$$/ { \
            print;  # 保留第一个分隔线
            skip_mode=2; \
            next; \
        } \
        skip_mode == 2 && /REPLACEMENT$$/ { \
            print tree;  # 替换占位符为tree输出
            skip_mode=3; \
            next; \
        } \
        skip_mode == 3 && /----$$/ { \
            print;  # 保留第二个分隔线
            skip_mode=0; \
            next; \
        } \
        !skip_mode || skip_mode !=2  # 非跳过模式或非占位符行正常输出
    ' README.md > tmp_tree.md && mv tmp_tree.md README.md

可选:用sed实现的方案(需要处理多行匹配)

如果你坚持要用sed,可以利用它的循环读取多行功能,但需要注意转义换行和特殊字符:

update-tree-with-sed:
    # 把tree输出的换行转义成\n,方便sed识别
    TREE_CONTENT=$$(tree | sed 's/[\/&]/\\&/g; s/$$/\\n/g' | tr -d '\n'); \
    sed -i.bak '/^\[fencedtitle\]$/{:loop;N;/----$$/!bloop;s/.*----\n.*\n----/'"$$TREE_CONTENT"'/}' README.md

说明:

  1. :loop;N;/----$$/!bloop是sed的多行循环:读取下一行,直到匹配到第二个----;
  2. s/.*----\n.*\n----/.../把整个围栏块替换成转义后的tree输出;
  3. -i.bak会生成原文件的备份(比如README.md.bak),如果不需要备份可以去掉.bak。

注意事项

  • 如果你需要排除某些目录/文件,可以给tree加参数,比如tree -I 'node_modules|.git';
  • 处理包含特殊字符(如/、&、$)的输出时,一定要先转义,避免替换命令出错;
  • 测试时可以先输出到临时文件,确认结果正确后再替换原文件,防止误改内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:08:46