sed 交换两行需用保持空间作中转,按行号交换时用“x”和“g”指令配合地址范围,如交换第2行与第5行:sed '2{x;d;};5{g;};x' file,加-i才修改原文件。

Linux 中用 sed 交换文件中两行位置,核心在于利用它的保持空间(Hold Space)作为临时“中转站”,配合模式空间(Pattern Space)完成跨行操作。它不依赖外部工具,纯命令行即可实现——但需注意:行号或匹配条件必须明确,且默认不修改原文件,加 -i 才能直接写入。
按行号交换(如第2行与第5行)
这是最直观的场景。假设要交换第 A 行和第 B 行(A
-
sed -n '2{h;d;}; 5{x;p;}; 5!{x;p;}' file.txt—— 简化版,仅适用于相邻或特定位置,稳定性有限 - 更通用可靠的方式是使用标签循环读取中间行:
-
sed -n '2{h;d;}; 5{g;s/\(.*\)\n\(.*\)/\2\n\1/;p;}; 5!{p;}' file.txt—— 但该写法未处理中间行,易出错 - 推荐标准写法(兼容 GNU sed):
-
sed -n '2{h;d;}; 5{x;G;s/\(.*\)\n\(.*\)\n\(.*\)/\3\n\2\n\1/;p;}; 5!{p;}' file.txt—— 需确保中间内容被正确捕获,实际中建议用下述结构化脚本
按匹配内容交换(如含 "start" 和 "end" 的行)
当目标行不确定具体行号,但有唯一标识(如某关键字),可用正则定位。关键点:前一行必须先被捕获并暂存,再等到后一行出现时统一重组。
- 基础逻辑:遇到第一行 → 存入保持空间 → 跳过输出;遇到第二行 → 取出保持空间内容,与当前行交换顺序输出
- 示例:交换含
<module>api</module>和<module>web</module>的两行(前者在前): sed -n '/<module>api/{h;d;}; /<module>web/{x;G;p;}; p' file.xml</module></module>- 若两行间有其他内容,需用
N多读几行,配合标签循环(如:a;N;/pattern/!ba)把中间段完整暂存
安全替换并保存到原文件
上述命令默认只输出结果,不改动源文件。如需直接修改,必须加 -i 选项:
- 直接覆盖:
sed -i '/start/{h;d;}; /end/{x;G;s/\(.*\)\n\(.*\)/\2\n\1/;p;}; p' file.conf - 带备份(强烈建议):
sed -i.bak '/start/{h;d;}; /end/{x;G;p;}; p' file.conf—— 会生成file.conf.bak - 注意 macOS 用户:BSD sed 语法略有差异,建议安装 GNU sed(
brew install gnu-sed),并用gsed命令替代
常见问题与避坑提示
实际使用中容易卡在几个细节上:
-
空行或特殊字符干扰:正则中的
/、.、$等需转义,或换用其他分隔符,如sed 's|old|new|g' -
匹配顺序很重要:若两个模式都可能在多行出现,需确保第一个匹配只触发一次(可加
q退出,或限定地址范围如1,/pattern1/{...}) -
保持空间未清空导致残留:多次运行前建议用
x清空或用sed -e '/pattern1/{h;d;}' -e '/pattern2/{x;G;p;}' file分开处理 -
非 GNU 环境兼容性:标签(
:a)、跳转(ba)、扩展正则(-r)在部分系统不支持,优先测试sed --version











