一起学习sed(四)

和awk一样,sed在执行命令的时候是按行来进行的,以行为单位。如果我们的操作设计到多个行,那么就需要使用参数“N”来声明了。
“N”表示当前操作的下一行,将当前行和下一行当作一个单位来进行操作。
比如,看一下下面这个命令的运行结果。

sed '=;N' example.txt
# 1
# This is a test file.
# It is the last day of 2018.
# 3
# Hope all you success!
# HAPPY NEW YEAR!

其中,“=”表示行号。sed在执行命令的时候,首先针对第一行执行,输出行号“1“;然后执行”N“,将第二行和第一行作为一个操作单位,输出;因为第二行已经被操作过,所以在此执行‘=;N’时,从第三行开始,输出行号“3”,然后输出第3行和第4行。
如果将上面操作顺序颠倒一下

 sed 'N;=' example.txt
# 2
# This is a test file.
# It is the last day of 2018.
# 4
# Hope all you success!
# HAPPY NEW YEAR

上面是先将两行合并为一个操作单位,然后再输出行号,注意这是的行号是第二行。

上面是偶数行的情况,如行数是奇数。那么最后一行由于没有找到下一行,将会结束sed命令。

 sed '$a The last line!' example.txt | sed "N;="
# 2
# This is a test file.
# It is the last day of 2018.
# 4
# Hope all you success!
# HAPPY NEW YEAR!
# The last line!

当执行最后一行时,没有找到下一行,所以后面的“=”命令也不会执行!这一点必须注意,否则容易出现bug。

同样的道理,如果是想将3行作为一个操作单位,那么可以使用两个“N”来表示。

sed '=;N;N' example.txt
# 1
# This is a test file.
# It is the last day of 2018.
# Hope all you success!
# 4
# HAPPY NEW YEAR!

应用:将两行合并为一行

如将结尾为叹号的相邻两行合并起来。是不是可以下面的写法:

sed '/!$/s/\n//g' example.txt

先找出以叹号结尾的行,然后将行后面的行分隔符“\n”删除!但是,这种方法不对!!因为,sed时以单行为单位进行处理的,即便你把一行的行分隔符删除,那么sed在输出结果的时候也会是单独一行。所以,正确的写法是:

sed '/!$/{N;s/\n//g}' example.txt
# This is a test file.
# It is the last day of 2018.
# Hope all you success!HAPPY NEW YEAR!

扩展:sed缓存

sed有两种缓存形式,一种是模式缓存(pattern buffer);另一种是暂留缓存(hold buffer)。模式缓存是你当下选择并读入的行;暂留缓存更像是一个长期存储空间,执行sed过程中,你可以把一些相关内容存入暂留缓存,在后面的sed执行中可以随地调用这些缓存中的内容。对这两种缓存的操作有以下常用的命令:

h : 模式缓冲中的内容复制到暂留缓存中,并覆盖之前暂留缓存中的内容
H :模式缓存中的内容添加到暂留缓存中,保留之前的暂留缓冲中的内容
g :暂留缓存中的内容复制到模式缓冲中,并覆盖当下模式缓存中的内容
G :暂留缓存中的内容添加到模式缓冲中,保留当下模式缓存中的内容
不过,引入这些缓存的概念使得sed过于复杂了,难以理解,不做深入探讨,此处仅举一例:将一个文本中的所有行逆序输出

sed -n '1!G;h;$p' example.txt 
# HAPPY NEW YEAR!
# Hope all you success!
# It is the last day of 2018.
# This is a test file.

针对第一行,使用“!”表示不执行G,因为此时暂留缓存是空白,不需要将暂留缓存添加到模式缓存,否则就会多出一行空白行;接下来执行h,将模式缓存(此时是第一行的全部内容)添加到暂留缓存;”$p”表示在最后一行执行输出,因而此处不执行输出。
针对第二行,执行G,将(第一行运行之后的)暂留缓存添加到模式缓存,此时的模式缓存变成了:

It is the last day of 2018.
This is a test file.

然后执行h,将上面的模式缓存,复制并覆盖之前的暂留缓存中,此时的暂留缓存也变成了:

It is the last day of 2018.
This is a test file.

接下来依次执行下面的其他行。
。。。
在最后一行,将暂留缓存中的内容打印出来,就完成了对一个文本的逆行输出!
还有更多的关于sed缓存的操作,不过有些难以理解。

===== THE END ====

参考资料:http://www.grymoire.com/Unix/Sed.html#uh-30

一起学习sed(四)

猜你喜欢

转载自blog.51cto.com/15069450/2577341