如何在同一sed命令内刷新输出行号 按新行号每10行插入分隔符
同一sed进程内实现输出行动态计数插入标记的方法
sed原生的步长地址匹配(比如1~10)、内置行号变量都是以原始输入流的行号为基准,插入/追加的新行不会被纳入计数,要基于实际输出内容的行号间隔插入标记,不需要管道串联多个sed进程,在单个sed脚本内手动维护输出计数器即可实现。
实现逻辑
- 关闭sed默认输出,所有输出内容由脚本主动控制,避免重复打印
- 在sed保持空间中存储独立的输出行计数器,和原始输入行号完全解耦
- 每输出1行内容(包括原始输入行、匹配pattern插入的行、插入的
####标记行),计数器自动+1 - 每次计数器更新后判断是否为10的倍数,满足条件则插入
####标记,同时计数器同步累加(标记行本身也算输出行)
可用脚本
sed脚本文件版本(保存为.sed文件加执行权限可直接调用)
#!/usr/bin/sed -nf # 初始化计数器:处理第一行前将保持空间的计数器值设为0 1 { h s/.*// s/^/0/ h } # 匹配pattern时插入指定行,同步更新计数 /pattern/ { i #inserting a line g s/.*/expr & + 1/e h s/.*/expr & % 10/e /^0$/ { i #### g s/.*/expr & + 1/e h } } # 输出当前原始输入行,计数器累加 p g s/.*/expr & + 1/e h # 判断是否达到10行间隔,满足则插入####并更新计数 s/.*/expr & % 10/e /^0$/ { x i #### x g s/.*/expr & + 1/e h }
命令行直接调用版本
sed -nf ' 1{h;s/.*//;s/^/0/;h;} /pattern/{i\#inserting a line g;s/.*/expr & + 1/e;h;s/.*/expr & % 10/e;/^0$/{i\#### g;s/.*/expr & + 1/e;h;} } p g;s/.*/expr & + 1/e;h s/.*/expr & % 10/e;/^0$/{x;i\#### x;g;s/.*/expr & + 1/e;h;} ' 目标文件路径
注意事项
- 上述脚本依赖GNU sed的
e替换修饰符,该修饰符可以执行替换位的shell命令并将结果写回模式空间,用来实现计数器的算术计算 - macOS/BSD系统自带的sed不支持
e修饰符,需要先安装GNU sed(通常包名为gsed)替换系统自带sed后再使用 - 所有计数完全基于实际输出的行,和原始文件行号无关,插入任意数量的新行都不会导致间隔标记偏移
内容的提问来源于stack exchange,提问作者Sharan Kumar
相关产品推荐
相关产品推荐

