今天继续介绍Linux三剑客中的sed

sed是stream editor(流编辑器)的缩写。它最常见的用法是进行文本替换。下面介绍一些sed的常见用法。

sed最常见的功能,是用它进行文本替换。它的替换形式和vim非常相似,具体语法如下:

 $ sed 's/pattern/replace_string/' file

其中pattern代表替换用的模式串,replace_string代表被替换的字符串。sed命令不改变原有的文件,如果想要直接替换原来的文件, 需要使用-i选项。

 $ sed -i 's/text/replace/' file

前面的例子只能替换了每行中模式首次匹配的内容。要实现全局替换必须使用g标记。

 $ sed 's/pattern/replace_string/g' file

/#g标记可以使sed替换第N次出现的匹配:

$ echo thisthisthisthis | sed 's/this/THIS/2g'
thisTHISTHISTHIS

$ echo thisthisthisthis | sed 's/this/THIS/3g'
thisthisTHISTHIS

$ echo thisthisthisthis | sed 's/this/THIS/4g'
thisthisthisTHIS

sed还可以用来对文本进行处理,例如删除空行。行可以用正则表达式 ^$ 进行匹配,用/d告诉sed不执行替换操作,而是直接删除匹配到的空行。

$ sed '/^$/d' file

注意这里开头没有s。

在sed中,我们可以用&指代模式所匹配到的字符串,这样就能够在替换字符串时使用已匹配的内容。例如下面这个例子:

 $ echo this is an example | sed 's/\w\+/[&]/g'
 [this] [is] [an] [example]

&指代匹配给定模式的字符串。我们还可以使用\#来指代出现在括号中的部分正则表达式(注:子模式)所匹配到的内容:

$ echo this is digit 7 in a number | sed 's/digit \([0-9]\)/\1/'
this is 7 in a number

这条命令将digit 7替换为7。\(pattern\)用于匹配子串,在本例中匹配到的子串是7。子模式被放入使用反斜线转义过的()中。对于匹配到的第一个子串,其对应的标记是\1,匹配到的第二个子串是\2,往后以此类推。我们还可以对这些匹配到的子串进行处理。

$ echo seven EIGHT | sed 's/\([a-z]\+\) \([A-Z]\+\)/\2 \1/'
EIGHT seven

上面这条命令中,\1匹配得到单词seven,\2匹配得到单词\EIGHT。在替换部分,它们的次序被更改为\2 \1,因此就呈现出了逆序的结果。

sed可以组合多个表达式来对文本进行替换,有三种表示方法:

$ sed 'expression' | sed 'expression' # 第一种
$ sed 'expression; expression' #第二种
$ sed -e 'expression' -e 'expression' # 第三种

它们使用的效果是相同的。

$ echo abc | sed 's/a/A/' | sed 's/c/C/'
AbC
$ echo abc | sed 's/a/A/;s/c/C/'
AbC
$ echo abc | sed -e 's/a/A/' -e 's/c/C/'
AbC

另外,在sed的表达式中可以使用变量,这时需要使用双引号。

$ text=hello
$ echo hello world | sed "s/$text/HELLO/"
HELLO world