Sed 入门教程

一. Sed 简介

Sed(Stream Editor),翻译过来就是流编辑器,通过 Sed 可以对 标准输出或者文件逐行 进行处理。

1. Sed 的命令格式

Sed 的命令格式主要有下面两种:

  • 基于标准输出的文本处理
stdout | sed [option]  "pattern command"
  • 基于文件的文本处理
sed [option] "pattern command" file

可以看到命令主要由三部分组成:

  • option:Sed 选项。用来控制处理流程,比如如何展示,是否将文本处理作用于源文件等。
  • pattern:匹配格式。用来进行文本匹配,结合正则表达式可以实现非常强大的文本匹配。
  • command:Sed 命令。用来指明进行什么操作,比如追加、替换、删除等操作。

由此我们可以想到 Sed 的工作方式就是: 遍历标准输出或者某个文件的每一行,然后对每一行的内容通过 pattern 进行匹配,将匹配到的内容基于 command 命令进行处理,然后根据 option 选项做对应的操作。接下来就看下 Sed 中常用的选项、命令的作用以及常用的 pattern 匹配模式。

二. Sed 的常用选项

-n:只显示 Sed 处理后的内容

首先我们创建一个测试文件,写入测试内容


# 测试文件内容
$ cat a.txt
first line
second line
third line
forth

不加选项,使用 p 命令将测试文件的内容打印一遍,/line/ 表示匹配有 line 的行。按理说应该只有 3 行匹配,但最终所有的原文都会被打印了一遍。

$ sed "/line/p" a.txt 
first line
first line
second line
second line
third line
third line
forth

现在加上 -n 选项重新执行命令,可以看到现在只打印匹配到的行了。

$ sed -n "/line/p" a.txt
first line
second line
third line

-e:以选项中指定的 script 处理文本,可以通过 -e 选项指定多个命令

如果我们想匹配 lineLINE,那么可以通过两个 -e 进行指定两个匹配模式,示例如下

$ cat a.txt
first LINE
second line
third line

$ sed -n  -e "/line/p" -e "/LINE/p" a.txt
first LINE
second line
third line

-r:支持扩展正则表达式

上面我们通过两个 -e 指定了两个匹配模式,分别查找 lineLINE 所在的行,其实这可以通过正则表达式实现,

在扩展正则表达式中有逻辑或 | 的操作,Sed 默认不支持该操作,需要通过 -r 选项使其支持扩展正则表达式,然后就可以使用逻辑或操作实现多个模式的匹配了,示例如下:

$ sed -n -r "/line|LINE/p" a.txt
first LINE
second line
third line

-f:以选项中指定的 script 文件处理文本

当操作的选项过多时,使用 -e 在命令行中指定多个显得有些繁琐,我们可以将 Sed 命令写到一个脚本中,然后通过 -f 命令指定该脚本运行即可。例如上面的 sed -n -e "/line/p" -e "/LINE/p" a.txt 命令可以通过执行 sed 脚本替换如下:

$ cat find.sed
/line/p
/LINE/p


$ sed -n -f find.sed a.txt
first LINE
second line
third line

下面是 [Linux命令行与shell脚本编程大全] (https://book.douban.com/subject/26854226/) 中的一个例子:

给出几行文本,将每行中的 brown 替换为 green,将 fox 替换为 elephant,将 dog 替换为 cat。如果通过 -e 选项则需要如下编写

➜  sed -e '
s/brown/green/
s/fox/elephant/
s/dog/cat/' data1.txt
The quick green elephant jumps over the lazy cat.
The quick green elephant jumps over the lazy cat.
The quick green elephant jumps over the lazy cat.
The quick green elephant jumps over the lazy cat.

通过编写脚本并使用 -f 选项就可以简化为下面的操作

# sed 脚本内容
➜  cat script1.sed
s/brown/green/
s/fox/elephant/
s/dog/cat/

# 通过 -f 指定 sed 脚本文件
➜  sed -f script1.sed data1.txt
The quick green elephant jumps over the lazy cat.
The quick green elephant jumps over the lazy cat.
The quick green elephant jumps over the lazy cat.
The quick green elephant jumps over the lazy cat.

-i:将编辑作用到源文件

Sed 的编辑默认是不会修改源文件的,我们可以通过 -i 选项改变这一点。示例如下:

# 将 line 替换为 LINE 并打印
$ sed -n "s/line/LINE/g;p" a.txt
first LINE
second LINE
third LINE

# 源文件没有变化
$ cat a.txt
first LINE
second line
third line

# 添加 -i 选项重新操作
$ sed -n -i "s/line/LINE/g;p" a.txt

# 源文件也发生了改变
$ cat a.txt
first LINE
second LINE
third LINE

-h:显示帮助

$ sed -h
sed: invalid option -- 'h'
Usage: sed [OPTION]... {script-only-if-no-other-script} [input-file]...

  -n, --quiet, --silent
                 suppress automatic printing of pattern space
  -e script, --expression=script
                 add the script to the commands to be executed
  -f script-file, --file=script-file
                 add the contents of script-file to the commands to be executed

 . . . 

三. Sed 常用的匹配格式

Sed 可以通过行号、行区间、正则匹配、正则区间匹配进行文本的匹配。简要总结如下:

【1】10command: 行号匹配,匹配第 10 行

示例

# 删除第 10 行
sed -i "10d" data.tx

【2】10,15command: 行区间匹配,匹配 10 ~ 15 行

示例

# 删除 10 ~ 15 行
sed -i "10,15d" data.txt

【3】10,+5command: 行号,范围匹配

示例

# 从第 10 行开始,删除后面 5 行,即删除 10 ~ 16 行
sed -i "10,+5d" data.txt

【4】 /pattern/command: 正则匹配

示例

# 删除以 Add 开头的行
sed -i "/^Add/d" data.txt

【5】/pattern1/,/pattern2/command: 正则区间匹配

从匹配到 pattern1 的行开始,到匹配到 pattern2 的行结束,如果一直没有匹配到 pattern2,那么 Sed 会一直匹配到文本最有一行。

示例

$ cat -n data1.txt
     1	First Line
     2	Add two
     3	Third Line
     4	Subtract three
     5	SecondLine


# 从以 Add 开头的行开始,删除到以 Substract 的行结束,预期删除 2 ~ 4 行的数据
$ sed -i "/^Add/, /^Subtract/d" data1.txt

$ cat -n data1.txt
     1	First Line
     2	SecondLine

【6】/pattern1/,3command: 正则、行号区间匹配

可以将行号和正则匹配进行过混合使用,两者位置没有限制。

示例

$ cat data3.txt
First 1
Second 2
Third 3
Forth 4
Fifth 5

# 打印 从匹配到 First 的行到 第 3 行
$ sed -n "/First/, 3p" data3.txt
First 1
Second 2
Third 3

# 从第 3 行开始打印,一直到匹配诶到 Forth 的行
# root @ node1 in ~/Shell/mooc-shell/cp06 [9:15:13]
$ sed -n "3,/Forth/p" data3.txt
Third 3
Forth 4

四. Sed 的常用命令

了解了常见的选项和匹配模式,接下来就是了解常用的命令了。命令的使用,就是结合上面提到的匹配模式,对匹配到的文本进行一系列的增删改查操作。

【1】p:打印命令

示例 1:打印第 3 行的内容

$ cat -n line.txt
     1	First line
     2	Second line
     3	Third line
$ sed -n "3p" line.txt
Third line

示例 2:打印 3 到 5 行的内容

$ sed -n "3,5p" line.txt
Third line
4 line
5 line

示例 3:打印以 root 开头的行

我们查询 /etc/passwd 文件中 root 用户的内容,命令如下:

$ sed -n "/^root/p" /etc/passwd
root:x:0:0:root:/root:/bin/zsh

【2】a/i/w/r 追加命令

追加相关的命令有 airw 四个,分别示例如下:

# 演示文本内容
$ cat data.txt
Dog
Cat
Orange
Apple

  • a 行后追加
# 在第 1 ~ 2 行后面添加 This is animal 的文本
$ sed  "1,2a This is animal" data.txt
Dog
This is animal
Cat
This is animal
Orange
Apple
  • i 行前追加
# 在第 3 ~ 4 前面添加 This is fruit 的文本
$ sed "3,4i This is fruit" data.txt
Dog
Cat
This is fruit
Orange
This is fruit
Apple

  • r 从外部文件读取,追加到匹配行后面
# 读取 test.txt 文件的内容,追加到 1 ~ 2 行后面
$ sed "1,2r test.txt" data.txt
Dog
I come from a file.
Cat
I come from a file.
Orange
Apple
  • w 将匹配的行写入外部文件
# 从 Dog 所在的行开始匹配,直到 Orange 所在行,将所有匹配到的行写入 test.txt 文件
$ sed -n "/Dog/, /Orange/w test.txt" data.txt

$ cat test.txt
Dog
Cat
Orange

【3】s: 替换命令

替换命令的格式如下:

# 将匹配到 old 文本替换为 new 文本,如果一行中有多处匹配,默认只替换第一个
s/old/new/flags:

flag 表示替换标记,有下面四个选项:

  • 数字:将匹配到的到的第 N 处进行替换
  • g:将匹配到的所有文本进行替换
  • p:将原先行打印出来
  • w:将替换的结果写到文件中

一般来说 数字g 用的较多,下面看几个相关示例:

# 测试文件内容
$ cat test.txt
line line line
cat  line  cat line
dog  line  dog line

示例 1:默认替换第 1 处

# 将每行中的 line 替换为 大写的 LINE
$ sed "s/line/LINE/" test.txt
LINE line line
cat  LINE  cat line
dog  LINE  dog line

示例 2:替换第 2 处

$ sed "s/line/LINE/2" test.txt
line LINE line
cat  line  cat LINE
dog  line  dog LINE

示例 3:全部替换

$ sed "s/line/LINE/g" test.txt
LINE LINE LINE
cat  LINE  cat LINE
dog  LINE  dog LINE

示例 4:从第 2 处开始替换

$ sed "s/line/LINE/2g" test.txt
line LINE LINE
cat  line  cat LINE
dog  line  dog LINE

【4】d: 删除命令

在上面介绍匹配模式的部分 -d 命令已经使用过了,所以这里就不做赘述了。

四. 反向引用

有时候我们希望在匹配到的文本基础之上进行改进,而不是完全替换掉。比如希望将文本中的 apple 全部变为复数形式 apples,这时候直接引用原文本,在原文本基础之上加一个 s 是很方便的操作,Sed 有两种方式可以实现对匹配文本的引用:

1. 使用&符号

示例

$ cat apple.txt
I have some apple

$ sed  "s/apple/&s/" apple.txt
I have some apples

可以看到原文本中的 apple 变为了 apples& 符号代表的就是匹配到的文本。



# root @ server001 in ~/Shell/mooc-shell/cp06 [9:16:07]
$ sed -i "s/Java../&s/g" test.txt

# root @ server001 in ~/Shell/mooc-shell/cp06 [9:16:28]
$ cat test.txt
I learn Javaees
I learn Javadds
2. 使用 \N 模式匹配 (N 表示数字)

\N 也可以引用匹配到文本,和 & 的不同在于:

& 只能引用全部,而 \N 的格式可以引用部分文本。可以将需要引用的部分用括号括起来,然后 \N 只会引用被括起来的部分,\1 表示被括起来的第 1 处,\2 表示第二处,依次类推。

Sed 中命令中的括号需要进行转义,示例如下:

$ cat test.txt
Cats and Dogs

# root @ node1 in ~/Shell/mooc-shell/cp06 [21:04:20]
# 匹配模式为 Cats + 字符串 + dogs 的文本
# 通过加括号,\1 表示 Cats,\2 表示 Dogs,将匹配到的两个单词中间加 `` love ``
$ sed "s/\(Cats\).*\(Dogs\)/\1 love \2/" test.txt
Cats love Dogs

以上即为 Sed 的简记,重点要理解 Sed 的工作方式,然后要熟练掌握还需要多加练习才行。

发布了46 篇原创文章 · 获赞 21 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/Ahri_J/article/details/102852463
sed