shell 编程三剑客之二:sed 详解

sed 是一种流式编辑器,属于行处理编辑器。和 grep 一样,也要大量用到正则表达式。

用法:

sed [OPTION]... {script-only-if-no-other-script} [input-file]...

选项:

-n, --quiet, --silent        屏蔽默认输出

-e script, --expression=script        指定需要执行的 sed 指令

-f script-file, --file=script-file        指定需要执行的 sed 脚本文件

--follow-symlinks        跟随软链接

-i[SUFFIX], --in-place[=SUFFIX]        直接修改原文件,如果提供了SUFFIX,备份数据

-l N, --line-length=N        指定每行的长度

--posix        使 GNU 扩展不生效

-E, -r, --regexp-extended        支持扩展正则

-s, --separate        将多个文件视为各自独立的

--sandbox        在沙盒模式执行(e/r/w 不生效)

-u, --unbuffered        从输入文件加载最少的数据,更频繁地刷新输出缓冲区

-z, --null-data        行分隔符配置为空

--help        帮助文档

--version        版本信息

如果没有给定 -e 或 -f,则第一个非选项参数被视为脚本,后边的所有参数被视为输入文件。如果没有输入文件,将会操作标准输入的数据。

操作指令:

1. 不和行定位一起使用的指令:

: label        定义在 b 或 t 指令中使用的 label

# comment        注释

2. 和 0 或 1 个行定位一起使用的指令:

=        打印当前行号

a \

text        在匹配行后一行追加 text

i \

text        在匹配行前一行插入 text

q [exit code]       立刻退出 sed 脚本,如果自动打印没有失效,打印当前模式空间内容

Q [exit code]        立刻退出 sed 脚本

r filename        追加 filename 中读取的内容

R filename        追加 filename 中一行内容,每次发出指令,读取一行

3. 和范围行定位一起使用的指令:

b label        跳转至 label 所在位置,如果没有提供 label,则跳转到指令的结尾

c \

text        指定行的内容替换成 text

d        删除指定行整行内容

D        删除模式空间中的第一行

g G        复制/追加保持空间内容到模式空间

h H        复制/追加模式空间内容到保持空间

l        把模式空间中的内容打印出来,非打印字符用两位ASCII码表示

l width        

n N        读取/追加下一行到模式空间

p        打印当前模式空间的内容

P        打印模式空间的第一行

s/pattern/replacement/flags

flags:n(1-512)表示需要替换的第n个pattern匹配的内容,g表示所有pattern都被替换,p表示把模式空间的内容打印, w后边接文件名表示把模式空间的内容输出到该文件

replacement的特殊符号:&表示pattern,\n表示在pattern里第n个用\(\)框起来的结构,\表示转义或换行。\L后边的字符都转成小写字母,\l后边的一个字符转成小写字母,\U后边的字符都转成大写字母,\u后边的一个字符转成大写字母,\E使因\U或\L发生的字母转换结束。

s///:表示将字符替换为空

t label        有条件跳转至 label 所在位置,如果没有提供 label,则跳转到指令的结尾

T label        条件不满足时跳转至 label 所在位置,如果没有提供 label,则跳转到指令的结尾

w filename        当前模式空间内容写入 filename

x        交换模式空间与保持空间的内容

y/source/dest/        source 中的每个字母替换成 dest 中对应位置的字母

定位方式:

number        行号

first~step        行号为 first 开始,步进 step

$        最后一行

/regexp/        正则表达式

\cregexpc        正则表达式,c 是任意字符

0, addr2        以“匹配的第一个地址”状态开始,直到找到addr2,addr2 是正则表达式

addr1, +N        addr1 开始及后面的 N 行

addr1, ~N        add1 开始,到下一个 N 的倍数的行

addr1, addr2        addr1 开始,addr2 结束

详细讲解:

一. 基础功能:

首先需要记住一点,在不指定 -n 的情况下,sed 指令生效后的文本会打印在标准输出,但除非使用 -i,否则不会对源文件进行修改。

1. 替换(s):

# cat sed_demo
The quick brown fox jumps over a lazy dog.
The quick brown fox jumps over a lazy dog.
The quick brown fox jumps over a lazy dog.
The quick brown fox jumps over a lazy dog.

# sed 's/a/e/' sed_demo
The quick brown fox jumps over e lazy dog.
The quick brown fox jumps over e lazy dog.
The quick brown fox jumps over e lazy dog.
The quick brown fox jumps over e lazy dog.
# sed 's/a/e/g' sed_demo
The quick brown fox jumps over e lezy dog.
The quick brown fox jumps over e lezy dog.
The quick brown fox jumps over e lezy dog.
The quick brown fox jumps over e lezy dog.
# sed 's/a/e/2' sed_demo
The quick brown fox jumps over a lezy dog.
The quick brown fox jumps over a lezy dog.
The quick brown fox jumps over a lezy dog.
The quick brown fox jumps over a lezy dog.
# sed 's/a/e/gp' sed_demo
The quick brown fox jumps over e lezy dog.
The quick brown fox jumps over e lezy dog.
The quick brown fox jumps over e lezy dog.
The quick brown fox jumps over e lezy dog.
The quick brown fox jumps over e lezy dog.
The quick brown fox jumps over e lezy dog.
The quick brown fox jumps over e lezy dog.
The quick brown fox jumps over e lezy dog.
# sed -n 's/a/e/gp' sed_demo
The quick brown fox jumps over e lezy dog.
The quick brown fox jumps over e lezy dog.
The quick brown fox jumps over e lezy dog.
The quick brown fox jumps over e lezy dog.
# sed 's/a/&n/' sed_demo
The quick brown fox jumps over an lazy dog.
The quick brown fox jumps over an lazy dog.
The quick brown fox jumps over an lazy dog.
The quick brown fox jumps over an lazy dog.
# sed 's/\(j\)um\(p\)s/\2lays/' sed_demo
The quick brown fox plays over a lazy dog.
The quick brown fox plays over a lazy dog.
The quick brown fox plays over a lazy dog.
The quick brown fox plays over a lazy dog.
# sed 's/a//' sed_demo
The quick brown fox jumps over  lazy dog.
The quick brown fox jumps over  lazy dog.
The quick brown fox jumps over  lazy dog.
The quick brown fox jumps over  lazy dog.
# sed 's/a//w sed_demo1' sed_demo
The quick brown fox jumps over  lazy dog.
The quick brown fox jumps over  lazy dog.
The quick brown fox jumps over  lazy dog.
The quick brown fox jumps over  lazy dog.
# cat sed_demo1
The quick brown fox jumps over  lazy dog.
The quick brown fox jumps over  lazy dog.
The quick brown fox jumps over  lazy dog.
The quick brown fox jumps over  lazy dog.

# sed '1s/a/e/g' sed_demo
The quick brown fox jumps over e lezy dog.
The quick brown fox jumps over a lazy dog.
The quick brown fox jumps over a lazy dog.
The quick brown fox jumps over a lazy dog.
# sed '$s/a/e/' sed_demo
The quick brown fox jumps over a lazy dog.
The quick brown fox jumps over a lazy dog.
The quick brown fox jumps over a lazy dog.
The quick brown fox jumps over e lazy dog.
# sed '2,3s/a/e/' sed_demo
The quick brown fox jumps over a lazy dog.
The quick brown fox jumps over e lazy dog.
The quick brown fox jumps over e lazy dog.
The quick brown fox jumps over a lazy dog.

# sed 's/lazy/\U&/' sed_demo
The quick brown fox jumps over a LAZY dog.
The quick brown fox jumps over a LAZY dog.
The quick brown fox jumps over a LAZY dog.
The quick brown fox jumps over a LAZY dog.
# sed 's/lazy/cra\Uzy/' sed_demo
The quick brown fox jumps over a craZY dog.
The quick brown fox jumps over a craZY dog.
The quick brown fox jumps over a craZY dog.
The quick brown fox jumps over a craZY dog.
# sed 's/lazy/\u&/' sed_demo
The quick brown fox jumps over a Lazy dog.
The quick brown fox jumps over a Lazy dog.
The quick brown fox jumps over a Lazy dog.
The quick brown fox jumps over a Lazy dog.
# sed 's/lazy/cra\uzy/' sed_demo
The quick brown fox jumps over a craZy dog.
The quick brown fox jumps over a craZy dog.
The quick brown fox jumps over a craZy dog.
The quick brown fox jumps over a craZy dog.
# sed 's/lazy/\Ucra\Ezy/' sed_demo
The quick brown fox jumps over a CRAzy dog.
The quick brown fox jumps over a CRAzy dog.
The quick brown fox jumps over a CRAzy dog.
The quick brown fox jumps over a CRAzy dog.

2. 删除(d):

# sed '2,3d;=' sed_demo
1
The quick brown fox jumps over a lazy dog.
4
The quick brown fox jumps over a lazy dog.

3. 增加(a):

# sed '2a \
additional line' sed_demo
The quick brown fox jumps over a lazy dog.
The quick brown fox jumps over a lazy dog.
additional line
The quick brown fox jumps over a lazy dog.
The quick brown fox jumps over a lazy dog.

4. 插入(i):

# sed '2i \
> inserted line' sed_demo
The quick brown fox jumps over a lazy dog.
inserted line
The quick brown fox jumps over a lazy dog.
The quick brown fox jumps over a lazy dog.
The quick brown fox jumps over a lazy dog.

5. 改变(c):

# sed '2c \
> changed line' sed_demo
The quick brown fox jumps over a lazy dog.
changed line
The quick brown fox jumps over a lazy dog.
The quick brown fox jumps over a lazy dog.

6. 转换(y):

# sed '2y/abc/xyz/' sed_demo
The quick brown fox jumps over a lazy dog.
The quizk yrown fox jumps over x lxzy dog.
The quick brown fox jumps over a lazy dog.
The quick brown fox jumps over a lazy dog.

7. 打印(p):默认会打印,为了清楚看到效果,使用 -n 隐藏默认打印

# sed -n '/T/p' sed_demo
The quick brown fox jumps over a lazy dog.
The quick brown fox jumps over a lazy dog.
The quick brown fox jumps over a lazy dog.
The quick brown fox jumps over a lazy dog.

8. 特殊打印(l):

# sed -n '/T/l' sed_demo
The quick brown fox jumps over a lazy dog.$
The quick brown fox jumps over a lazy dog.$
The quick brown fox jumps over a lazy dog.$
The quick brown fox jumps over a lazy dog.$

9. 打印行号(=):

# sed -n '3=' sed_demo
3
# sed -n '/^T/=' sed_demo
1
2
3
4

10. 退出(q):注意不要在指定 -i 时使用q,这样会把指定的行前边的行覆盖源文件,造成数据丢失。

# sed '2q' sed_demo
The quick brown fox jumps over a lazy dog.
The quick brown fox jumps over a lazy dog.

11. 读文件(r):

读取 sed_demo2 追加到 sed_demo 的第 3 行后:

# cat sed_demo2
1 The quick brown fox jumps over a lazy dog.
2 The quick brown fox jumps over a lazy dog.
3 The quick brown fox jumps over a lazy dog.
4 The quick brown fox jumps over a lazy dog.

# sed '3r sed_demo2' sed_demo
The quick brown fox jumps over a lazy dog.
The quick brown fox jumps over a lazy dog.
The quick brown fox jumps over a lazy dog.
1 The quick brown fox jumps over a lazy dog.
2 The quick brown fox jumps over a lazy dog.
3 The quick brown fox jumps over a lazy dog.
4 The quick brown fox jumps over a lazy dog.
The quick brown fox jumps over a lazy dog.

12. 写文件(w):

把 sed_demo 的前两行写到 output 中:

# sed -n '1,2w output' sed_demo
# cat output
The quick brown fox jumps over a lazy dog.
The quick brown fox jumps over a lazy dog.

二. 模式空间与保持空间:

模式空间是一块活跃的缓冲区,在 sed 执行命令时它会保存待检查的文本。但它并不是sed保存文本的唯一空间。另一块缓冲区域称作保持空间。在处理模式空间中的某些行时,可以用保持空间来临时保存一些行。sed 处理数据的流程大致如下图:

shell 编程三剑客之二:sed 详解_第1张图片

图中的箭头为数据流向,橙色箭头代表必要流程,蓝色箭头代表可选流程。数据是以行为单位进行流转的。

三. 进阶功能:

1. 下一行(n):

# cat sed_demo2
1 The quick brown fox jumps over a lazy dog.

2 The quick brown fox jumps over a lazy dog.

3 The quick brown fox jumps over a lazy dog.

4 The quick brown fox jumps over a lazy dog.
# sed 'n;d' sed_demo2
1 The quick brown fox jumps over a lazy dog.
2 The quick brown fox jumps over a lazy dog.
3 The quick brown fox jumps over a lazy dog.
4 The quick brown fox jumps over a lazy dog.

从第一行开始,把下一行删除,留下的就是奇数行,由于偶数号都是空行,所以打印出来的效果是空行都被删除了。

2. 与下一行合并(N):

# cat sed_demo2
1 The quick brown fox jum
ps over a lazy dog.
2 The quick brown fox jumps over a lazy dog.
3 The quick brown fox jumps over a lazy dog.
4 The quick brown fox jumps over a lazy dog.
# sed '1N;s/\n//' sed_demo2
1 The quick brown fox jumps over a lazy dog.
2 The quick brown fox jumps over a lazy dog.
3 The quick brown fox jumps over a lazy dog.
4 The quick brown fox jumps over a lazy dog.

这段命令的功能是把第一行的下一行和第一行合并,都放到模式空间,之后用s命令把换行符替换成空字符,把两行输出成一行。

3. 删除模式空间中的第一行(D): 

# sed '1N;/jum\nps/D' sed_demo2
ps over a lazy dog.
2 The quick brown fox jumps over a lazy dog.
3 The quick brown fox jumps over a lazy dog.
4 The quick brown fox jumps over a lazy dog.

4. 模式空间与保持空间之间的交互(h H g G x):

# cat sed_demo2
1 The quick brown fox jumps over a lazy dog.
2 The quick brown fox jumps over a lazy dog.
3 The quick brown fox jumps over a lazy dog.
4 The quick brown fox jumps over a lazy dog.
# sed '1{h;d};2{H;d};4G' sed_demo2
3 The quick brown fox jumps over a lazy dog.
4 The quick brown fox jumps over a lazy dog.
1 The quick brown fox jumps over a lazy dog.
2 The quick brown fox jumps over a lazy dog.

首先将第1行复制放到保持空间,从模式空间删除第1行,接着把第2行复制并放到保持空间中的下一行,从模式空间删除第2行,现在保持空间就有了第一行和第二行的内容。然后执行把保持空间的内容追加到模式空间第4行的后面。 

# sed '1h;2H;3x' sed_demo2
1 The quick brown fox jumps over a lazy dog.
2 The quick brown fox jumps over a lazy dog.
1 The quick brown fox jumps over a lazy dog.
2 The quick brown fox jumps over a lazy dog.
4 The quick brown fox jumps over a lazy dog.

首先将第1行复制放到保持空间,接着把第2行复制并放到保持空间中的下一行,然后把模式空间的第3行和保持空间的内容交换。

5. 取反命令(!):

# sed -n '1!p' sed_demo2
2 The quick brown fox jumps over a lazy dog.
3 The quick brown fox jumps over a lazy dog.
4 The quick brown fox jumps over a lazy dog.

除了第1行,都打印 

# sed -n '1!G;h;$p' sed_demo2
4 The quick brown fox jumps over a lazy dog.
3 The quick brown fox jumps over a lazy dog.
2 The quick brown fox jumps over a lazy dog.
1 The quick brown fox jumps over a lazy dog.

文本内容倒序。整个流程为:除了第一行,每次读取一行到模式空间后就把保持空间的内容追加到模式空间,之后再把模式空间的内容覆盖保持空间,重复这一步骤,直到最后一行。

6. 标签的使用(: b t):

未定义标签时,b默认跳到脚本末尾,也就是说匹配的位置的行不操作,下边这个例子中,2 3 两行不执行替换,1 4 行执行了替换。

# sed '2,3b;s/fox/cat/' sed_demo2
1 The quick brown cat jumps over a lazy dog.
2 The quick brown fox jumps over a lazy dog.
3 The quick brown fox jumps over a lazy dog.
4 The quick brown cat jumps over a lazy dog.

下边的命令中,用 :branch 定义了名为 branch 的标签,在第1行和第4行时跳到标签处,标签前的命令不执行,后边的执行。其他行正常执行所有命令。

# sed '1b branch;4b branch;s/fox/cat/;:branch;s/jumps/flies/' sed_demo2
1 The quick brown fox flies over a lazy dog.
2 The quick brown cat flies over a lazy dog.
3 The quick brown cat flies over a lazy dog.
4 The quick brown fox flies over a lazy dog.

下边的命令中,先把 2 到 4 行删掉,重点演示第 1 行的执行过程,先定义一个标签 branch,然后把匹配到的第 1 个 o 替换为 a,之后如果替换成功则跳到 branch,再次执行替换,直到替换操作未能执行为止。

# sed '2,4d;:branch;s/o/a/p;t branch;' sed_demo2
1 The quick brawn fox jumps over a lazy dog.
1 The quick brawn fax jumps over a lazy dog.
1 The quick brawn fax jumps aver a lazy dog.
1 The quick brawn fax jumps aver a lazy dag.
1 The quick brawn fax jumps aver a lazy dag.

你可能感兴趣的:(linux命令详解,shell,编程教程,bash,开发语言,linux,正则表达式)