shell脚本编程系列
前面使用sed编辑器的基础命令时,所有的命令都是针对单行数据执行操作的。在sed编辑器读取数据流时,它会根据换行符的位置将数据分成行。sed编辑器会根据定义好的脚本命令,一次处理一行数据,然后移到下一行重复这个流程。但是有可能查找的短语出现在两行当中,此时普通的sed编辑器命令是无能为力的。所以,sed编辑器提供了3个可用于处理多行文本的特殊命令。
- N:加入数据流中的下一行,创建一个多行组进行处理
- D: 删除多行组中的第一行
- P: 打印多行组中的第一行
next命令
- 单行next命令
单行next(n)命令会告诉sed编辑器移动到数据流中的下一行,不用再返回到命令列表的最开始位置。通常sed编辑器在移动到数据流中的下一行之前,会在当前行中执行完所有定义好的命令,而单行next命令改变了整个流程。比如删除指定的空行,可以先找到目标行,然后使用单行next命令移动到文本的下一行,再执行删除操作、sed '/Header/{n;d}' data1.txt
- 多行next命令
单行next命令会将数据流中的下一行移入sed编辑器的工作空间(称为模式空间)。而多行版本的next(N)命令则是将下一行添加到模式空间中已有文本之后。这样的结果是将数据流中的两行文本合并到同一个模式空间中。文本行之间仍然用换行符分隔,但sed编辑器现在会将两行文本当作一行来处理。sed '/First/{N;s/\n/ /}' data2.txt
N命令可用于在数据文件中查找可能会分散在两行中的文本sed 'N;s/System.Admin/DevOps Engineer/' data3.txt
上面虽然解决了匹配多行的问题,但是最后两行合并到了一起,可能并不是我们想要的结果,此时可以考虑在sed编辑器中用两个替换命令,一个用来处理短语出现在多行中的情况,一个用来处理短语出现在单行的情况sed 'N;s/System\nAdmin/DevOps\nEngineer/;s/System Admin/DevOps Engineer/' data3.txt
上面的脚本存在一个不易察觉的问题,因为脚本在执行sed编辑器命令时总会先将下一行文本读入模式空间,但当抵达最后一行文本时,就会没有下一行可读,这时N命令会叫停sed编辑器。如果要匹配的文本正好在最后一行,那么命令就无法找到要匹配的数据,此时需要将单行编辑命令放在N命令之前即可sed 's/System Admin/DevOps Engineer/;N;s/System\nAdmin/DevOps\nEngineer/' data4.txt
多行删除命令
对于单行删除(d)命令,sed编辑器用该命令来删除模式空间中的当前行,然而,与N命令一起使用时,则必须小心单行删除命令
sed 'N;/System\nAdmin/d' data4.txt
sed编辑器提供了多行删除(D)命令,该命令只会删除模式空间中的第一行,即删除该行中的换行符及其之前的所有字符。
sed 'N;/System\nAdmin/D' data4.txt
结合N命令和D命令可以删除数据流中出现在第一行之前的空行
sed '/^$/{N;/Header/D}' data5.txt
多行打印命令
多行打印命令(P)只打印模式空间的第一行,即打印模式空间中换行符及其之前的所有字符。当用-n选项来抑制脚本输出时,它和显示文本的当行p命令大同小异。
sed -n 'N;/System\nAdmin/P' data3.txt
P命令的强大之处体现在其和N命令和D命令配合使用的时候.D命令的独特之处在于其删除模式空间中的第一行之后,会强制sed编辑器返回到脚本的起始处,对当前模式空间中的内容重新执行此命令。在脚本中加入N命令,就能单步扫过整个模式空间,对多行进行匹配
[root@192 Chapter21-Scripts]# sed -n '
> N
> s/#\n@//
> P
> D
> ' corruptData.txt