sed脚本之删除结尾的空白行
目标:
删除文件结尾的全部空白行,保留开头和中间的所有空白行(如果有的话)
样本数据:
$cat data
This is one
This is two
This is three
This is four
$
脚本:
$sed '{
:start
/^\n*$/{$d; N; b start}
}' data
输出:
$cat result
This is one
This is two
This is three
This is four
整个脚本工作流程:
1、读入一行写入模式空间。
2、根据/^\n*$/判断是否为空行,若不是空行则将模式空间输出到STDOUT,清空模式空间,跳转到步骤1.
若为空行,则判断是否是最后一行,若是最后一行则删除模式空间中所有内容,否则删除命令不执行。之后执行N,将下一行读入模式空间。执行b start。对当前模式空间重新执行步骤2。
当步骤2中N命令写入的是非空行的时候,模式空间无法匹配/^\n*$/,判定为非空行。
在整个脚本中需要注意好几个点,否则对脚本的运行过程会不理解。
1、N命令会将下一文本行添加到模式空间中已有的文本后。这里需要注意的是,当前行永远是模式空间中行号最大的行。
2、正则匹配时,模式空间中的内容被看做一个整体,例如,模式空间中的内容为
\n\n
abc
那么/^\n*$/也不会将\n\n匹配出来,因为模式空间中的结尾为abc。
3、分支命令b跳转到start标签后,被操作的模式空间仍为跳转前的模式空间,没有被清除。
例如
$cat data
123
abc
$sed '{
:start
p; start
}' data
输出为
123
123
123
123
123
4、关于sed输出规则,当对当前模式空间中的内容执行完所有命令后,会将模式空间中的内容输出到STDOUT来打印到屏幕上,并将模式空间清空。用以下文本内容作为例子。
$cat data
This is one
$
运行脚本,将空行替换为@
$sed 's/^\n*$/@/' data
@
This is one
$
模式空间导入第一行,经/^\n*$/匹配判断为空行,则运行替换。命令完成,输出并清空模式空间。
模式空间导入第二行,经匹配判断为非空行,不执行替换,命令完成,输出并清空模式空间。
而开头的删除文本结尾空白行的脚本,在运行到b start后直接跳转到了start标签处,所有的命令并没有执行完成,所以模式空间得到保留。直到读取到最后一行或不满足文本匹配的时候所有命令才执行完毕,模式空间得到输出并清空。
上一篇: SHELL删除空白行