关于sed中{//!p;}的含义、名称及多场景跳行用法的技术咨询
{//!p;}及跳过多行的扩展用法 我来帮你拆解这个sed命令的细节,以及扩展实现跳过多行的需求,顺便也补充下其他工具的替代方案:
一、{//!p;}的名称与核心作用
首先,这个是sed的反向匹配条件打印命令块,拆解来看:
//!:这是sed的反向地址匹配语法,翻译成大白话就是“不匹配当前地址范围起始模式(也就是/pattern match/)的行”p:sed的打印命令,配合开头的-n参数(默认不输出所有行,只打印指定行),专门用来输出符合条件的内容{}:把命令包裹成块,明确这个条件只作用在/pattern match/,$这个地址范围内(从匹配行到文件末尾)
所以整个{//!p;}的作用就是:在从匹配行到文件末尾的范围内,跳过匹配模式的那一行,只打印它之后的所有内容。
举个实际例子,如果你的Readme内容是:
前置行1 前置行2 pattern match 匹配行 后续行1 后续行2
执行sed -n '/pattern match/,${//!p;}' Readme后,只会输出后续行1和后续行2,完美跳过了匹配行本身。
二、如何实现跳过多行而非仅匹配行
如果你的需求是跳过匹配行之后的N行,或者从匹配行之后第M行开始打印到末尾,这里给你几个实用场景的实现:
场景1:跳过匹配行+后面2行,从第3行开始打印到末尾
比如想跳过匹配行,以及它后面连续2行,从第3行开始输出:
sed -n '/pattern match/{n;n;n; :loop; p; n; b loop}' Readme
解释下逻辑:
- 定位到匹配行后,用3次
n命令——每次n都会读取下一行并替换当前模式空间,相当于跳过了匹配行+后面2行,停在目标起始行 :loop定义一个循环标签,p打印当前行,n读取下一行,b loop跳回标签继续循环,直到文件结束
场景2:从匹配行之后第K行开始,直接打印到末尾(GNU sed专属简洁写法)
如果你用的是GNU sed(大多数Linux系统默认都是),可以直接用偏移语法:
sed -n '/pattern match/+3,$p' Readme
这里+3表示从匹配行之后的第3行开始,$代表文件末尾,直接打印这个范围的所有行。
场景3:跳过匹配行后所有空行,从第一个非空行开始打印
如果要跳过匹配行之后的连续空行,直到遇到非空行再开始输出:
sed -n '/pattern match/{:skip_empty; n; /^$/b skip_empty; :print_loop; p; n; b print_loop}' Readme
逻辑是:定位到匹配行后,进入skip_empty循环,只要读取到空行就继续跳过;遇到非空行后,进入print_loop循环开始打印所有后续内容。
三、用grep/awk实现类似需求
你提到的其他工具确实也能轻松搞定,给你几个常用写法:
awk实现(跳过匹配行,打印之后所有内容)
awk的逻辑更直观,用一个标记变量控制打印:
awk '/pattern match/{flag=1; next} flag' Readme
解释:匹配到模式时,设置flag=1,并用next跳过当前行;之后只要flag为1,就打印所有行。
grep实现(打印匹配行之后所有内容,再删除匹配行)
利用grep的-A参数打印匹配行之后的内容,再删掉第一行(匹配行):
grep -A 99999 'pattern match' Readme | sed '1d'
-A 99999表示打印匹配行之后的99999行(足够覆盖绝大多数文件),如果你的文件特别大,可以用grep -A "$(wc -l < Readme)"来动态获取文件总行数,避免行数不够的问题。
内容的提问来源于stack exchange,提问作者Prabhat Kumar Singh

