9、Linux文本处理三剑客之sed命令

Linux 用于处理文本数据的三剑客,分别为 grep 命令、awk 命令和 sed 命令,再加上正则表达式,就可以处理文本文件中各种常见的数据需求了。一般来说,grep 命令倾向于查找,sed 命令倾向于编辑更新,awk 命令则倾向于数据的分析和处理,本篇将重点梳理 sed 命令及常见的使用场景。

一、sed 简介

sed 是文本处理中非常好用的工具,能够完美的配合正则表达式,主要用来自动编辑一个或多个文件,可将数据进行替换、删除、新增、选取特定行等操作,从而简化对文件的反复操作,编写转换程序等。处理时,先把当前处理的行存储在临时缓冲区中(模式空间),接着用 sed 命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。然后,处理下一行,这样不断重复,直到文件处理结束。
sed 命令的使用格式,如下:

sed [参数选项] 操作

参数选项有:

  • -e:直接使用命令行模式进行 sed 相关的操作;
  • -n:表示操作使用安静模式,避免所有来自 stdin 的数据打印输出;
  • -r:表示操作使用的是扩展型正则表达式的语法;
  • -f:表示执行文件内的 sed 相关操作;
  • -i:表示直接修改读取的文件内容,而不输出打印;

操作行为有:(为了描述方便,使用 x,y 表示数字)

  • a:新增,比如 ‘xa 字符串’,表示在第 x 行的下一行,新增该字符串作为新的一行;
  • i:插入,比如 ‘xi 字符串’,表示在第 x 行的上一行,插入该字符串作为新的一行;
  • d:删除,比如 ‘xd’,表示删除第 x 行的数据;又比如 ‘x,yd’,表示删除第 x 行到第 y 行的数据;又比如 ‘x,$d’,表示删除第 x 行到最后一行的数据(美元符号表示最后的含义);
  • c:替换,比如 ‘xc 字符串’,表示用该字符串替换第 x 行的数据;又比如 ‘x,yc’,表示用该字符串替换第 x 行到第 y 行的数据;
  • p:查询,将选择的数据打印显示,通常和-n参数搭配使用,比如 sed -n ‘x,yp’,表示打印显示第 x 行到第 y 行的数据;
  • s:替换,直接替换匹配到的文本内容,通常和正则表达式搭配使用,比如 sed -i 's/原字符串/新字符串/g ',表示用新字符串替换所有的旧字符串;
  • w:写入,将原文件的内容或按条件匹配到的内容写到另一个目标文件中。

二、sed 常见的操作

搞懂了 sed 命令的相关知识点后,可以动动手验证,并练习下常见的文本操作了,以 demo.txt 文件为例演示。

[xxw@localhost ~]$ cat demo.txt 
hello
very nice

lalalala

11111111|22222222|333333?
44444444?|5555?5555|666666?

lalalala
today is nice
gogogogog
lalalala

yyds

1、新增操作

<1>、在文件首行添加一行 “I want to fly” 字符串,使用 i 操作符(当前行的上一行)

[xxw@localhost ~]$ sed -i '1i I want to fly' demo.txt
[xxw@localhost ~]$ cat demo.txt
I want to fly
hello
very nice

lalalala
(后面显示省略....

注意:要想保存修改后的文件,需要使用重定向生成新的文件,或者直接修改源文件本身,则需要使用“-i”参数。

<2>、在文件最后一行添加一行 “process over” 字符串,使用 a 操作符(当前行的下一行)

[xxw@localhost ~]$ sed -i '$a process over' demo.txt
[xxw@localhost ~]$ cat demo.txt
(前面显示省略....)
lalalala

yyds
process over

<3>、在文件第5行的前后各添加一行

[xxw@localhost ~]$ sed -i '5i AAAAAAAAA' demo.txt
[xxw@localhost ~]$ sed -i '5a BBBBBBBBB' demo.txt
[xxw@localhost ~]$ cat demo.txt
I want to fly
hello
very nice

AAAAAAAAA
BBBBBBBBB
lalalala
(后面显示省略....

<4>、在文件第2行的后面添加3行数据(使用 \ 增加行数)

[xxw@localhost ~]$ sed -i '2a xxxxxxxxx\
>yyyyyyyyyy\
>zzzzzzzzzzzzz' demo.txt
[xxw@localhost ~]$ cat demo.txt
I want to fly
hello
xxxxxxxxx
yyyyyyyyyy
zzzzzzzzzzzzz
very nice
(后面显示省略....

2、删除操作

<1>、删除第一行、最后一行、含指定字符串的行

#删除第一行
[xxw@localhost ~]$ sed -i '1d' demo.txt
#删除最后一行
[xxw@localhost ~]$ sed -i '$d' demo.txt
[xxw@localhost ~]$ cat demo.txt
hello
xxxxxxxxx
yyyyyyyyyy
zzzzzzzzzzzzz
very nice
(中间显示省略....)
lalalala

yyds
#删除含有xiang字符串的行
[xxw@localhost ~]$ sed -i '/xiang/d' demo.txt
#删除含有数字结尾的行【亲测可用】
#[xxw@localhost ~]$ sed -i '/[0-9]$/d' demo.txt
#删除以小字母开头的行【亲测可用】
#[xxw@localhost ~]$ sed -i '/^[a-z]/d' demo.txt

<2>、删除第2行~第4行的数据

[xxw@localhost ~]$ sed -i '2,4d' demo.txt
[xxw@localhost ~]$ cat demo.txt
hello
very nice

AAAAAAAAA
(中间显示省略....)
lalalala

yyds

<3>、删除空白行

[xxw@localhost ~]$ sed -i '/^$/d' demo.txt
[xxw@localhost ~]$ cat demo.txt
hello
very nice
AAAAAAAAA
BBBBBBBBB
lalalala
(中间显示省略....)
lalalala
yyds

<4>、删除每一行的指定字符(比如删除 nice 字符串)

[xxw@localhost ~]$ sed -i 's/nice//g' demo.txt
[xxw@localhost ~]$ cat demo.txt
hello
very 
AAAAAAAAA
BBBBBBBBB
lalalala
(中间显示省略....)
today is 
gogogogog
lalalala
yyds

3、修改/替换操作

<1>、把第2行~第4行替换成字符串"666666"(操作符 c 用于整行替换)

[xxw@localhost ~]$ sed -i '2,4c 666666' demo.txt
[xxw@localhost ~]$ cat demo.txt
hello
666666
lalalala
(中间显示省略....)
today is 
gogogogog
lalalala
yyds

<2>、把文本中的所有小写字母a转成大写A

[xxw@localhost ~]$ sed -i 's/a/A/g' demo.txt
[xxw@localhost ~]$ cat demo.txt
hello
666666
lAlAlAlA
(中间显示省略....)
todAy is 
gogogogog
lAlAlAlA
yyds

注意:‘s/旧字符串/新字符串/g’ 把文本中匹配到的所有旧字符串替换成新的字符串,请注意,操作符 g 表示会匹配每一行的所有字符串。
==> 如果只需要匹配每一行的第3个符合条件的字符串并替换,把 g 换成 3 即可:(方便演示,这里不再添加 -i 参数修改文本)

[xxw@localhost ~]$ sed 's/a/A/3' demo.txt
hello
666666
lalalAla
(中间显示省略....)
today is 
gogogogog
lalalAla
yyds

==> 如果在 行首 或 行末尾 或 指定行范围 插入指定字符串:(方便演示,这里不再添加 -i 参数修改文本)

# 在每行行首插入指定字符串012U
[xxw@localhost ~]$ sed 's/^/012U/' demo.txt
012Uhello
012U666666
012Ulalalala
(中间显示省略....)
012Utoday is 
012Ugogogogog
012Ulalalala
012Uyyds
# 在每行行末尾插入指定字符串012U
[xxw@localhost ~]$ sed 's/$/012U/' demo.txt
hello012U
666666012U
lalalala12U
(中间显示省略....)
today is 012U
gogogogog012U
lalalala012U
yyds012U
# 在第2行~第3行的行末尾插入指定字符串012U
[xxw@localhost ~]$ sed '2,3s/$/012U/' demo.txt
hello
666666012U
lalalala012U
(中间显示省略....)
today is 
gogogogog
lalalala
yyds

==> 另外,如果把A字符改成空字符,则表示删除所有的a字符:(方便演示,这里不再添加 -i 参数修改文本)

[xxw@localhost ~]$ sed 's/a//g' demo.txt
hello
666666
llll
(中间显示省略....)
tody is 
gogogogog
llll
yyds

<3>、把文本中的每一行末尾的?,替换成!

[xxw@localhost ~]$ sed -i 's/\?$/\!/g' demo.txt
11111111|22222222|333333!
44444444?|5555?5555|666666!

4、查询操作

<1>、查找第3行到第5行内容(操作符 p 不搭配 -n 使用,则会重复输出第3行到第5行内容)

[xxw@localhost ~]$ sed -n '3,5p' demo.txt
lAlAlAlA
11111111|22222222|333333!
44444444?|5555?5555|666666!

<2>、分别查找偶数行奇数行的内容

# 查找偶数行
[xxw@localhost ~]$ sed -n 'n;p' demo.txt
666666
11111111|22222222|333333!
lAlAlAlA
gogogogog
yyds
# 查找奇数行
[xxw@localhost ~]$ sed -n 'p;n' demo.txt
hello
lAlAlAlA
44444444?|5555?5555|666666!
todAy is 
lAlAlAlA

注意:查找偶数行和奇数行,也可以使用这种方式:

# 查找偶数行
[xxw@localhost ~]$ sed -n '2~2p' demo.txt
# 查找奇数行
[xxw@localhost ~]$ sed -n '1~2p' demo.txt

<3>、查找有特定字符串的行内容

# 查找含有"lAlA"字符串的所有行
[xxw@localhost ~]$ sed -n '/lAlA/p' demo.txt
lAlAlAlA
lAlAlAlA
lAlAlAlA
# 查找包含指定单词的行,\<单词\>表示单词边界
[xxw@localhost ~]$ sed -n '/\/p' demo.txt
todAy is 
# 查找以wei字符串开头的行
[xxw@localhost ~]$ sed -n '/^wei/p' demo.txt
# 查找以xiang字符串结尾的行
[xxw@localhost ~]$ sed -n '/.xiang/p' demo.txt
# 查找以数字结尾的行
[xxw@localhost ~]$ sed -n '/[0-9]$/p' demo.txt
666666
11111111|22222222|333333!
44444444?|5555?5555|666666!

5、多点编辑操作

使用 -e 参数,可以在同一行里执行多条命令。比如,先在每行的行首添加 012U 字符串,再在最后一行添加 “I like you” 字符串。

[xxw@localhost ~]$ sed -e 's/^/012U/' -e '$a I like you' demo.txt
012Uhello
012U666666
012UlAlAlAlA
(中间显示省略....)
012UtodAy is 
012Ugogogogog
012UlAlAlAlA
012Uyyds
I like you

请注意,多条命令是按顺序执行的,不同的顺序将产生不同的结果,如果把第二个命令放在最前面,则 “I like you” 字符串会变成 “012UI like you” 。当然,-e 参数也可以换成 --expression 。

6、文件备份

使用操作符 w 可以备份原文件的内容到另一个文件。比如,把 demo.txt 文件内容全部备份到 demo1.txt。

[xxw@localhost ~]$ sed 'w demo1.txt' demo.txt
hello
666666
lAlAlAlA
(中间显示省略....)
todAy is 
gogogogog
lAlAlAlA
yyds

# 如果不想打印备份时屏幕输出的这些内容,可以使用-n参数
[xxw@localhost ~]$ sed -n 'w demo1.txt' demo.txt
[xxw@localhost ~]$ cat demo1.txt
hello
666666
lAlAlAlA
(中间显示省略....)
todAy is 
gogogogog
lAlAlAlA
yyds

还有一种情况,如果我只需要备份符合条件的行数据到另一个文件,那可以使用正则表达式匹配:

# 把数字开头的行数据,备份到demo2.txt文件
[xxw@localhost ~]$ sed -n '/^[0-9]/w demo2.txt' demo.txt
[xxw@localhost ~]$ cat demo2.txt
666666
11111111|22222222|333333!
44444444?|5555?5555|666666!

以上是 sed 命令常见的使用场景,结合正则表达式,它还能处理更为复杂的场景,以下是 sed 命令常用的正则表达式匹配:
9、Linux文本处理三剑客之sed命令_第1张图片
关于 sed 命令的相关脚本,后续自己会收集梳理,再去更新吧,这里不再说明了。

最后

本篇重点梳理了 sed 命令的用法,并对常见使用场景进行演示,sed 作为一种文本编辑的强大工具,通常需要搭配正则表达式使用,才能完美的处理更为复杂的需求。另外,sed 本身也是一个管道命令,也可以与 grep、awk 等常见的命令搭配使用,它常被用在 shell 脚本的编写,值得我们去学习和掌握。

你可能感兴趣的:(Linux,linux,sed命令)