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替换的方法相对于别的语言来说有很大的优势
    "世界上只有一种真正的英雄主义,就是认清了生活的真相后,还依然执着地热爱它。"
                                                                   ——罗曼·罗兰
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号