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

如何用sed实现跨行文本剪切追加的原地替换?

解决方案

可以用sed实现这个需求,核心是利用sed的**保持空间(Hold Space)**暂存需要移动的内容,结合多行模式处理完成剪切和追加操作。

具体sed命令

直接在bash脚本中使用以下命令即可批量处理文件:

sed -i -e '
/^find.* | while/,/^done/{
    # 处理范围起始行(find开头的行)
    /^find.* | while/{
        # 提取| while之前的内容
        s/\(.*\) | while/\1/
        # 存入保持空间
        h
        # 清空当前模式空间,跳过后续处理
        s/.*//
        b
    }
    # 处理中间以| while开头的行
    /^| while/{
        # 先移除行首的|,再提取| while之前的内容
        s/^| \(.*\) | while/\1/
        # 追加到保持空间
        H
        # 清空当前模式空间,跳过后续处理
        s/.*//
        b
    }
    # 处理范围结束行(done行)
    /^done/{
        # 交换模式空间与保持空间(此时保持空间存的是所有待追加内容)
        x
        # 把保持空间里的换行替换为空格
        s/\n/ /g
        # 给内容包裹< <()
        s/^/ < <(/
        s/$/)
        # 把原done行追加回来(原done行在交换后的保持空间里)
        G
    }
}' "$changeme"

命令解释

  1. 范围限定:/^find.* | while/,/^done/{...} 只处理从匹配find开头且包含| while的行,到匹配done的行这个区间内的内容。
  2. 起始行处理:提取该行| while之前的部分,存入保持空间后清空当前行,最终输出为空(相当于删除原行的这部分内容,只保留后面的while...)。
  3. 中间行处理:先移除行首的|,再提取| while之前的部分,追加到保持空间,同样清空当前行,只保留后面的内容。
  4. done行处理:将保持空间里的所有暂存内容拼接成一行,用< <()包裹,再和原done行拼接,最终输出done < <(...)的形式。

示例验证

输入示例

find /var/log -name "*.log" | while read logfile
| grep "error" "$logfile" | while read errline
| echo "Error found: $errline"
done

输出结果

while read logfile
grep "error" "$logfile" | while read errline
echo "Error found: $errline"
done < <(find /var/log -name "*.log" grep "error" "$logfile" echo "Error found: $errline")

注意事项

  • 若在macOS环境下使用,sed -i需要添加空参数,即改为sed -i '' -e '...',否则会生成带后缀的备份文件。
  • 确保目标文件中find...| while和done的配对是正确的,避免跨区间的内容被错误处理。
  • 如果区间内存在空白行或不符合匹配规则的行,需要根据实际情况调整正则表达式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 23:07:13