shell中sed命令-N选项的理解

最近用到shell中的sed命令,当时对于-N选项的用法很疑惑,后经过思索终于弄明白了,写在这里记录一下。

  • sed命令的版本
  • -N选项用法示例
  • 原理分析

注意:熟悉sed的s替换命令;熟悉换行符\n;系统环境 ubuntu 14.04 lts。

sed命令的版本

使用sed - -version来查看当前sed命令的版本,我这里使用的版本如下:

sed (GNU sed) 4.2.2
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

-N选项用法示例

data.txt文件,包含内容如下(数字和冒号为行号,请忽略):

1: next next next next time hello
2: word next next next next
3: next hello word next next
4: next next next hello word next
5: next next next next next hello
6: word next next next.

sed_n.sh文件,包含内容如下:

#!/bin/bash

sed '{
    s/hello word/hello shell/
    N
    s/hello\nword/hello\nshell/
    s/hello word/hello shell/
}' data3.txt

我们的目的是要将data.txt文件中的hello word替换为hello shell。
执行./sed_n.sh文件的结果如下:

next next next next time hello
shell next next next next
next hello shell next next
next next next hello shell next
next next next next next hello
shell next next next.

可以看见已经成功的将hello word替换为了hello shell。


原理分析

sed命令内部有一个缓冲区,保存着当前读取的内容,每次只会读取一行内容。同时内部还维护一个指针,指向当前读取的行数。

最初的时候缓冲区为空,同时指针指向0行,即没有执向具体的行数。

首先sed命令会读取第一行的内容“next next next next time hello”,此时指针指向第一行。接着会用第一条命令 “s/hello word/hello shell/” 来进行处理,发现没有匹配的,那么就开始执行第二条命令 “N”,这条命令会将第二行的内容“word next next next next”读到与第一行内容相同的缓冲区并追加在后面,同时指针指向第二行。接着用第三条命令“s/hello\nword/hello\nshell/”来进行处理,发现有匹配成功的地方那么就执行s替换命令。最后再执行第四条命令“s/hello word/hello shell/”,没有匹配的地方,则不执行任何操作。

经过上面的流程后,sed接着开始读取,清空缓冲区,因为指针指向第二行,所以现在读取2+1行,即第三行,接着用第一条命令进行匹配,发现有匹配成功的地方则进行替换。然后执行第二条命令 “N” 读取第四行的内容并追加在第三行的后面,同时移动指针指向第四行。接着执行第三条命令,发现没有匹配的地方则不做任何操作,最后执行第四条命令,发现刚追加的第四行内容有匹配的地方,然后进行替换。

最后第五和第六行的执行流程同上,这里就不再分析了。