如何使用sed匹配并替换连续两行内容?
解决连续数字开头行的交换与去数字问题
我明白你遇到的痛点了——直接用N命令会把非数字开头的行也卷进来,导致匹配逻辑混乱,没法精准定位连续两行都是数字开头的情况。下面我给你两种可靠的解决方案,分别用sed和awk实现,完全符合你的需求:
方案1:用sed精准匹配处理
sed的核心思路是只对数字开头的行触发后续逻辑,避免误读非目标行。命令如下:
sed -E ':loop; /^[0-9]/ {N; /\n[0-9]/ {s/^[0-9](.*)\n[0-9](.*)/\2\n\1/; b loop}; P; D}' 你的文件名.txt
逐部分解释:
-E:启用扩展正则,不用转义括号,写法更简洁:loop:定义循环标签,处理完一组连续行后可以回头检查新的行组合/^[0-9]/ { ... }:只有当前行以数字开头时,才执行大括号内的操作N:读取下一行到模式空间,此时模式空间是行1\n行2/\n[0-9]/ { ... }:检查第二行是否也以数字开头,是的话执行替换s/^[0-9](.*)\n[0-9](.*)/\2\n\1/:捕获两行数字后的内容,交换位置并去掉开头数字b loop:回到循环标签,确保如果交换后仍有连续数字行,能继续处理
P; D:如果第二行不是数字开头,就打印模式空间的第一行,删掉它后重新处理剩余内容,不破坏原有行结构
方案2:用awk实现更直观的逻辑
awk的变量特性让我们可以轻松保存上一行内容,逻辑更易懂:
awk ' prev ~ /^[0-9]/ && /^[0-9]/ { sub(/^[0-9]/, "", prev) sub(/^[0-9]/, "", $0) print $0 print prev prev = "" next } prev != "" { sub(/^[0-9]/, "", prev) print prev } { prev = $0 } END { if (prev != "") { sub(/^[0-9]/, "", prev) print prev } }' 你的文件名.txt
逻辑说明:
- 用
prev变量缓存上一行内容 - 当当前行和上一行都以数字开头时,去掉两行的开头数字,先打印当前行再打印上一行(完成交换),然后清空
prev - 如果
prev不为空,说明上一行无法和当前行组成连续数字行,打印去数字后的prev - 最后缓存当前行到
prev,END块处理最后一行剩余内容
测试示例
拿你提供的示例文件2来说,假设原内容是:
adfa adaf dfd aaa 1 1a 2 2b 3 3d sdfa 4 4a 5 5b 6 6d 7 7k
执行命令后,输出会变成:
adfa adaf dfd aaa 2b 1a 3d sdfa 4a 5b 6d 7k
完全符合“交换连续数字行+去开头数字”的要求。
内容的提问来源于stack exchange,提问作者Wang
相关产品推荐
相关产品推荐

