$ sed -i 's/Hello/Hi/g' sed.txt
$ cat sed.txt ## 我们看到源文件的内容已经被修改了
Hi PHP
Hi Shell
Hi C
sed 的 pattern
sed 是通过对文本流逐行进行模式的匹配,然后应用命令,从而来达到对文本流的转换。那 sed 都有哪些常用的 pattern 模式呢? 如下表所示:
匹配模式
含义
10command
匹配到第10行
10,20command
匹配从第10行开始,到第20行结束
10,+5command
匹配从第10行开始,到第16行结束
/pattern1/command
匹配到 pattern1 的行
/pattern1/,/pattern2/command
匹配从满足 pattern1 的行开始,到满足 pattern2 的行结束
10,/pattern1/command
匹配从第10行开始,到匹配到 pattern1 的行结束
/pattern1/,10command
匹配从满足 pattern1 的行开始,到第10行结束
针对上面的这些匹配模式,示例如下:
$ sed -n '2p' /etc/passwd ## 打印第二行
bin:x:1:1:bin:/bin:/sbin/nologin
$ sed -n '2,3p' /etc/passwd ## 打印第二到第三行
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
$ sed -n '2,+2p' /etc/passwd ## 打印第二到第四行
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
$ sed -n '/root/p' /etc/passwd ## 打印匹配 root 的行
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
$ sed -n '/halt/,/games/p' /etc/passwd ## 打印匹配 hatl 到 匹配 games 之间的行
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
$ sed -n '3,/adm/p' /etc/passwd ## 打印从第三行开始,到匹配 adm 的行结束
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
$ sed -n '/adm/,5p' /etc/passwd ## 打印从匹配 adm 的行开始,到第 5 行结束
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sed 中的命令
前文中讲解了 sed 中的 pattern,接着我们再来看看 sed 中的各类命令,无外乎是增上改查,如下表所示:
类别
命令
含义
查询
p
打印
增加
a
行后增加
i
行前增加
r
外部文件读入,行后追加
w
匹配行写入外部文件
删除
d
删除
修改
s/old/new
将行内第一个 old 替换成 new
s/old/new/g
将行内全部的 old 替换成 new
s/old/new/2g
将行内前 2 个 old 替换成 new
s/old/new/ig
将行内 old 全部替换成 new,忽略大小写
为了接下去的演示,我们先创建一个 vim 的配置文件,位于 ~/.vimrc ,内容如下:
syntax on
set nu
set ts=2
删除
现在来演示删除命令:
$ sed -i '/syntax/d' ~/.vimrc ## 删除匹配 syntax 的一行配置
$ cat ~/.vimrc ## 输出内容,可见已经被删除了
set nu
set ts=2
新增
在删除了之后,我们恢复这行配置:
$ sed -i '/nu/a syntax\ on' ~/.vimrc ## 空格需要使用转义字符(\)转义
$ cat ~/.vimrc ## 输出内容如下,在匹配 nu 的后面一行增加了 syntax on 配置
set nu
syntax on
set ts=2
上面演示了命令 a 的用法,命令 i 也是类似,前者是在匹配行的行后增加,后者是在行前增加。然后我们演示如何使用 -r 命令,从指定的文件追加内容:
## 首先创建一个配置文件
cat <<EOF > config.txt
> set showcmd
> set encoding=utf-8
> set t_Co=256
> EOF
## 然后将这个文件追到到 ~/.vimrc 中
sed -i '/ts/r config.txt' ~/.vimrc
## 再来看看现在 ~/.vimrc 中的内容
$ cat ~/.vimrc ## 输出内容如下
set nu
syntax on
set ts=2
set showcmd
set encoding=utf-8
set t_Co=256
命令 w 是将匹配的行写入到指定的文件中:
$ sed -n '/ts/,/Co/w /tmp/result.txt' ~/.vimrc ## 将符合 ts 匹配的行到符合 Co 匹配的行之间的内容输出到 /tmp/result.txt 文件中
$ cat /tmp/result.txt ## 输出内容如下
set ts=2
set showcmd
set encoding=utf-8
set t_Co=256
更新
然后,我们在来演示一下更新:
## 将符合文本 ts=2 换成 ts=4,注: 这表示每个制表符(tab)等于 n 个空格
$ sed -i 's/ts=2/ts=4/' ~/.vimrc
## 上面的示例是将第一个匹配的修改,如果需要全局的话,如下
$ sed -i 's/ts=2/ts=4/g' ~/.vimrc
## 如果需要忽略大小写
$ sed -i 's/ts=2/ts=4/i' ~/.vimrc
## 如果需要全局忽略大小写的话
$ sed -i 's/ts=2/ts=4/gi' ~/.vimrc
需要注意,上面说的全局的范围是文本流的行,而不是整个文本流。比如说 sed -i 's/ts=2/ts=4/2g' ~/.vimrc 表示一行中替换前两个匹配的字符串。
再来看一个例子,如果我需要将文本中的 nu 这个缩写换成完整的单词 number, 可以使用 反向引用 ,即引用我匹配到的文本:
## & 就表示反向引用,这里指的是引用了 nu,在实际的引用场景中,往往是对前面正则匹配的文本的引用
$ sed -i 's/nu/&mber/g' ~/.vimrc
$ cat ~/.vimrc | grep nu ## 输出: set number
此外,文章详述了 sed 中的各种 pattern 匹配模式,如行号、行范围以及基于正则表达式的匹配,并通过实例展示了这些模式的具体应用。同时,还列举了 sed 中的核心命令,包括查询命令(如p打印匹配行)、增加命令(如a追加到匹配行后方, i插入到匹配行前方, r从外部文件读入并追加, w将匹配 行写入外部文件)、删除命令(如d删除匹配行)和修改命令(如s用于替换字符串,可控制替换次数和是否忽略大小写)。
文中以创建和编辑.vimrc配置文件为例,生动地演示了 sed 的删除、新增、替换及追加外部文件内容等实用功能,并强调了反向引用在替换命令中的重要作用 。最后说明了单引号和双引号在编写sed命令时的区别,即双引号会解析内部的变量。总之,本文全面而深入地介绍了sed工具的使用方法及其在文本处理中的强大能力。