sed进阶N;P;D

案例

sed 的高级替换

$cat file1
why:1
why:2
3
4
5
why:6
why:7
8
why:9

$cat file2
why:1
why:2 3 4 5
why:6
why:7 8
why:9

解决方法

sed ':1;N;/\nwhy/!s/\n/ /;t1;P;D' file
sed ':1;N;/\n.*:/!s/\n/ /;t1;P;D' file

解释

sed以行为单位处理文本,其模式缓冲区内只保留一行内容待处理。
:t 定义label "t",标签。相当于C语言里面的goto语句

	b label ,无条件跳转到标签label;
		如果label没有指定,跳转到命令的结尾
	t标签触发的条件是:
		必须t标签前的s///命令执行成功,否则忽略t标签

N 命令,将下一行读入并附加到当前行后面,
	以\n(换行符)分隔,一起存在模式缓冲区内。
s/\n/ / 这是sed中的替换命令,将\n替换为空格
\n 就表示换行符
/\n.*:/!s/\n/ /   匹配到\n.*:内容时,不执行替换;否则将\n换成空格

P打印当前模式空间开端至\n的内容,并追加到默认输出之前。
N命令简单来说就是追加下一行到模式空间,同时将两行看做一行,
	但是两行之间依然含有\n换行符,然后执行后续命令。
	然后再读取新行,对新读取的内容重头执行sed。
	此时,新读取的行会覆盖之前的行(之前的两行已经合并为一行)。
D删除模板块(缓冲区)的第一行。(并且回到sed命令的最开始)
$cat file1
why:1
why:2
3
4
5
why:6
why:7
8
why:9


sed ':1;N;/\n.*:/!s/\n/ /;t1;P;D' file

sed读取文件是否等于添加到模式空间
D命令是删除当前模式空间开端至\n的内容(不在传至标准输出),放弃之后的命令,但是对剩余模式空间重新执行sed

sed默认读取"指针"指定的行并且执行完成命令后会清空模式空间;但D命令不会清空模式空间, 会重返命令行首再次执行命令

完整的执行过程如下:

模式空间内容 执行命令
why:1 sed读取文件第1行
why:1 :1标签(以下每次执行忽略)
why:1\nwhy:2 执行命令N
why:1\nwhy:2 执行命令/\n.*😕!s/\n/ /;不满足条件,不执行替换
why:1\nwhy:2 执行命令t1 由于没有执行替换,忽略命令
why:1\nwhy:2 执行命令P,输出why:1
why:2 执行命令D 删除why:1
* D命令作用,继续从第一条命令开始执行
why:2\n3 执行命令N
why:2 3 执行命令/\n.*😕!s/\n/ /;满足条件,将\n替换为空格
why:2 3 执行命令t1 执行了替换,切换到标签1处
why:2 3\n4 执行命令N
why:2 3 4 执行命令/\n.*😕!s/\n/ /;满足条件,将\n替换为空格
why:2 3 4 执行命令t1 执行了替换,切换到标签1处
why:2 3 4\n5 执行命令N
why:2 3 4 5 执行命令/\n.*😕!s/\n/ /;满足条件,将\n替换为空格
why:2 3 4 5 执行命令t1 执行了替换,切换到标签1处
why:2 3 4 5\nwhy:6 执行命令N
why:2 3 4 5\nwhy:6 执行命令/\n.*😕!s/\n/ /;不满足条件,不执行替换
why:2 3 4 5\nwhy:6 执行命令t1 由于没有执行替换,忽略命令
why:2 3 4 5\nwhy:6 执行命令P,输出why:2 3 4 5
why:6 执行命令D,删除why:2 3 4 5
* D命令作用,继续从第一条命令开始执行
why:6\nwhy:7 执行命令N
why:6\nwhy:7 执行命令/\n.*😕!s/\n/ /;不满足条件,不执行替换
why:6\nwhy:7 执行命令t1 由于没有执行替换,忽略命令
why:6\nwhy:7 执行命令P,输出why:7
执行命令D 删除why:7
* D命令作用,继续从第一条命令开始执行
why:7\n8 执行命令N
why:7 8 执行命令/\n.*😕!s/\n/ /;满足条件,将\n替换为空格
why:7 8 执行命令t1 执行了替换,切换到标签1处
why:7 8\nwhy:9 执行命令N
why:7 8\nwhy:9 执行命令/\n.*😕!s/\n/ /;不满足条件,不执行替换
why:7 8\nwhy:9 执行命令P,输出why:7 8
why:9 执行命令D 删除why:7 8
why:9 执行命令N(到文件最后了)
why:9 执行命令/\n.*😕!s/\n/ /;不满足条件,不执行替换
why:9 执行命令P,输出why:9
why:9 执行命令D 删除why:9
执行完毕

这种sed替换的方法相对于别的语言来说有很大的优势

参考链接1

参考链接2

posted @ 2017-12-10 21:59  陈浩然201  阅读(286)  评论(0编辑  收藏  举报