文本三剑客之sed编辑器

107 阅读14分钟

文本三剑客:都是按行读取后处理。

  • grep 过滤行内容。
  • awk 过滤字段。
  • sed 过滤行内容;修改行内容。

1 sed编辑器

sed是一种流编辑器,流编辑器会在编辑器处理数据之前基于预先提供的一组规则来编辑数据流。

sed编辑器可以根据命令来处理数据流中的数据,这些命令要么从命令行中输入,要么存储在一个命令文本文件中。

sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。

2 sed的工作流程

sed的工作流程主要包括读取、执行和显示三个过程:

  • 读取: sed从输入流 (文件、管道、标准输入) 中读取一行内容并存储到临时的缓冲区中(又称模式空间,pattern space )。
  • 执行: 默认情况下,所有的sed命令都在模式空间中顺序地执行,除非指定了行的地址,否则sed命令将会在所有的行上依次执行。
  • 显示: 发送修改后的内容到输出流。在发送数据后,模式空间将会被清空。在所有的文件内容都被处理完成之前,上述过程将重复执行, 直至所有内容被处理完。

在所有的文件内容都被处理完成之前,上述过程将重复执行,直至所有内容被处理完。

注意:默认情况下所有的sed命令都是在模式空间内执行的,因此输入的文件并不会发生任何变化,除非使用"sed -i"修改源文件、或使用重定向输出到新的文件中。

3 sed命令格式

命令格式:

 sed -e '操作' 文件1 文件2
 sed -n -e '操作' 文件1 文件2
 sed -f  脚本文件  文件1 文件2
 sed -i -e '操作' 文件1 文件2
复制代码

执行多条命令的三种方法:

 sed -n -e '操作1' -e '操作2' 文件
 ​
 sed -n -e '操作1;操作2' 文件
 ​
 sed -e 'n{
 操作1
 操作2
 ......
 }' 文件1
复制代码

常用选项:

选项作用
-e 或--expression=表示用指定命令来处理输入的文本文件,只有一个操作命令时可省略,一般在执行多个操作命令使用
-f 或--file=表示用指定的脚本文件来处理输入的文本文件
-h 或--help显示帮助
-n、--quiet或--silent禁止sed编辑器输出,但可以与p命令一起使用完成输出
-i直接修改目标文本文件

常用操作:

操作作用
s替换,替换指定字符
d删除,删除选定的行
a增加,在当前行下方增加一行指定内容
i插入,在选定行上方插入一行指定内容
c替换,将选定行替换为指定内容
y字符转换,转换前后的字符长度必须相同
p打印行内容。如果同时指定行,表示打印指定行;如果不指定行,则表示打印所有内容;如果有非打印字符,则以ASCII码输出。其通常与"-n"选项一起使用
=打印行号
l (小写L)打印数据流中的文本和不可打印的ASCII字符(比如结束符$、制表符\t)

sed的核心功能:增删改查(可配合正则表达式)

 查: p
 ​
 删: d
 ​
 改: s(字符串替换)、c(整行替换)、y(对应字符进行替换,效果类似tr命令)
 ​
 增: i(在行前插入内容)、a(在行后添加内容)、r(在行后读入文件的内容)
 ​
 复制粘贴:H(复制)、d(删除)、G(粘贴到指定行下方)
复制代码

4 sed 查找打印p

4.1 不指定行(顺序处理每一行)

1、sed编辑器默认输出行内容,-n选项可以禁止输出。如果不加-n,却使用p操作,那么每行内容会打印两次。

sed -e "p" :每行内容打印两次。

sed -n "p" :每行内容只打印一次。

 [root@yuji ~]# cat ff.txt    //查看文件内容,共10行
 one
 two
 three
 four
 five
 six
 seven
 eight
 nine
 ten
 [root@yuji ~]# sed -e 'p' ff.txt     //每行内容会打印两次
 one
 one
 two
 two
 three
 three
 four
 four
 five
 five
 six
 six
 seven
 seven
 eight
 eight
 nine
 nine
 ten
 ten
 [root@yuji ~]# sed -n -e 'p' ff.txt    //每行内容只打印一次
 one
 two
 three
 four
 five
 six
 seven
 eight
 nine
 ten
复制代码

1.png

1-2.png

1-3.png

2、'n' 打印行号。

sed -n '=' :只打印行号。

sed -e 'n' : 打印行号和行内容。

sed -n '=;p' :打印行号和行内容。

 [root@yuji ~]# sed -n '=' ff.txt      //只打印行号
 1
 2
 3
 4
 5
 6
 7
 8
 9
 10 
 [root@yuji ~]# sed -e '=' ff.txt     //打印行号和行内容
 1
 one
 2
 two
 3
 three
 4
 four
 5
 five
 6
 six
 7
 seven
 8
 eight
 9
 nine
 10
 ten
复制代码

2-1行号.png

2-2行号.png

2-3行号.png

3、sed 执行多条命令的三种方法。

以打印行号和行内容为例:

 #方法一
 sed -n -e '=' -e 'p'  file.txt
 ​
 #方法二
 sed -n -e '=;p'  file.txt
 ​
 #方法三:换行操作
 sed -n '
 =
 p
 ' file.txt
复制代码

4、'l' 打印文本即隐藏字符(结束符$,制表符\t)。

 [root@yuji ~]# sed -n 'l' ff.txt
 one$
 two$
 three$
 four$
 five$
 six$
 seven$
 eight$
 nine$
 ten$
复制代码

4 打印文本及隐藏字符.png

4.2 sed 对指定行进行操作

两种方法:

  1. 以数字形式表示行区间;
  2. 用文本模式(字符串)来过滤出行(一般结合正则表达式)。

以数字形式表示行区间:

操作含义
'1p'打印第一行
'$p'打印最后一行
'1,3p'打印连续行,打印第一行到第三行
'6,$p'打印第六行到最后一行
'1,+3p'打印第一行加后面三行(即打印第一到第四行)
'5q'打印前五行后退出
'p;n'打印奇数行
'n;p'打印偶数行

使用字符串匹配出行:

操作含义
'/root/p'打印包含root的行
'/root/!p'打印不包含root的行。! 表示取反
'/^root/p'打印以root开头的行
'/bash$/'打印以bash结尾的行
'/root l bash/p'打印包含root或bash的行。"l"是扩展正则表达式的元字符,要使用sed -r
'6,/root/p'打印第6行到第一个包含root的行

4.2.1 以数字形式表示行区间

1、打印单行。

 [root@yuji ~]# sed -n '1p' ff.txt
 one
 [root@yuji ~]# sed -n '3p' ff.txt
 three
 [root@yuji ~]# sed -n '$p' ff.txt    //打印最后一行
 ten
 [root@yuji ~]# sed -n -e '1p' -e '5p' ff.txt    //打印第一行、第五行
 one
 five
复制代码

5单行.png

2、打印连续的行,使用逗号。

 [root@yuji ~]# sed -n '1,3p' ff.txt
 one
 two
 three
 [root@yuji ~]# sed -n '6,$p' ff.txt
 six
 seven
 eight
 nine
 ten
复制代码

6连续行.png

3、'1,+3p',打印第1行加后面3行(即打印第1~4行)。

 [root@yuji ~]# sed -n '1,+3p' ff.txt
 one
 two
 three
 four
复制代码

7第1行加后面3行.png

4、打印第1~5行的三种方法:

 [root@yuji ~]# sed -n '1,5p' ff.txt
 one
 two
 three
 four
 five
 [root@yuji ~]# sed -n '1,+4p' ff.txt
 one
 two
 three
 four
 five
 [root@yuji ~]# sed -e '5q' ff.txt
 one
 two
 three
 four
 five
复制代码

8前5行.png

5、使用sed输出奇数行或者偶数行。

'n' :next,读取下一行。

'p' :打印当前所在行。

 [root@yuji ~]# sed -n 'p;n' ff.txt
 one
 three
 five
 seven
 nine
 [root@yuji ~]# sed -n 'n;p' ff.txt
 two
 four
 six
 eight
 ten
复制代码

9奇数行偶数行.png

6、打印除了第一行以外的奇数行。

 [root@yuji ~]# sed -n '2,${n;p}' ff.txt
 three
 five
 seven
 nine
复制代码

9-2.png

7、比较 'p;n;p' 和 'n;p;n' 。

 [root@yuji ~]# sed -n 'p;n;p' ff.txt
 one
 two
 three
 four
 five
 six
 seven
 eight
 nine
 ten
 [root@yuji ~]# sed -n 'n;p;n' ff.txt
 two
 five
 eight
复制代码

10pnp.png

小贴士:

 'n' :next,读取下一行。
 'p' :打印当前所在行。
 ​
 # 'p;n' 处理过程:
 自动读取第1行,p打印第1行,n读取第2行;
 自动读取第3行,p打印第3行,n读取第4行;
 自动读取第5行,p打印第5行,n读取第6行;
 ......
 ​
 # 'n;p' 处理过程:
 自动读取第1行,n读取第2行,p打印第2行;
 自动读取第3行,n读取第4行,p打印第4行;
 自动读取第5行,n读取第6行,p打印第6行;
 ......
 ​
 # 'p;n;p' 处理过程:
 自动读取第1行,p打印第1行,n读取第2行,p打印第2行;
 自动读取第3行,p打印第3行,n读取第4行,p打印第4行;
 自动读取第5行,p打印第5行,n读取第6行,p打印第6行;
 ......
 ​
 # 'n;p;n' 处理过程:
 自动读取第1行,n读取第2行,p打印第2行,n读取第3行;
 自动读取第4行,n读取第5行,p打印第5行,n读取第6行;
 自动读取第7行,n读取第8行,p打印第8行,n读取第9行;
 ......
 以此类推。
复制代码

4.2.3 使用正则表达式,匹配行内容

注意:sed 使用扩展正则表达式时,要加 -r 。

示例1:

先将/etc/passwd 文件复制到家目录下并改名为pass.txt,方便演示。

[root@yuji ~]# cp /etc/passwd pass.txt        //复制文件并改名
[root@yuji ~]# sed -n '/root/p' pass.txt      //打印包含root的行
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@yuji ~]# sed -n '/^root/p' pass.txt      //打印以root开头的行
root:x:0:0:root:/root:/bin/bash
[root@yuji ~]# sed -n '/bash$/p' pass.txt      //打印以bash结尾的行
root:x:0:0:root:/root:/bin/bash
yuji2:x:1000:1000:yuji2:/home/yuji2:/bin/bash
nancy:x:1021:1021::/home/nancy:/bin/bash
helen:x:1022:1022::/home/helen:/bin/bash
复制代码

11root.png

示例2:

 [root@yuji ~]# sed -n '6,/root/p' pass.txt    //从第6行开始打印,一直到第一个包含root的行
 sync:x:5:0:sync:/sbin:/bin/sync
 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
 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
 [root@yuji ~]# sed -n '6,/root/=' pass.txt    //从从第6行开始打印行号,一直到第一个包含root的行
 6
 7
 8
 9
 10
复制代码

11root2.png

示例3:

sed -r 支持扩展正则表达式。同时在 使用{n}、{n,}、{n,m}时,括号{}前不需要加反斜杠\ 。

 [root@yuji ~]# sed -n '/ro{2,}t/p' pass.txt
 root:x:0:0:root:/root:/bin/bash
 operator:x:11:0:operator:/root:/sbin/nologin
 [root@yuji ~]# sed -n -r '/ro{2,}t/p' pass.txt
 root:x:0:0:root:/root:/bin/bash
 operator:x:11:0:operator:/root:/sbin/nologin
 ​
 #打印包含root或bash的行
 [root@yuji ~]# sed -n  '/root|bash/p' pass.txt     //如果不加-r,则"|"前要加转义符\
 root:x:0:0:root:/root:/bin/bash
 operator:x:11:0:operator:/root:/sbin/nologin
 yuji2:x:1000:1000:yuji2:/home/yuji2:/bin/bash
 nancy:x:1021:1021::/home/nancy:/bin/bash
 helen:x:1022:1022::/home/helen:/bin/bash
 [root@yuji ~]# sed -n -r '/root|bash/p' pass.txt   //"sed -r"支持扩展正则表达式
 root:x:0:0:root:/root:/bin/bash
 operator:x:11:0:operator:/root:/sbin/nologin
 yuji2:x:1000:1000:yuji2:/home/yuji2:/bin/bash
 nancy:x:1021:1021::/home/nancy:/bin/bash
 helen:x:1022:1022::/home/helen:/bin/bash
复制代码

11root3.png

11root4.png

5 sed 删除d

示例1:

以数字形式表示行区间。

 [root@yuji ~]# cat ff.txt
 one
 two
 three
 four
 five
 six
 seven
 eight
 nine
 ten
 [root@yuji ~]# sed '3d' ff.txt     //删除第3行
 one
 two
 four
 five
 six
 seven
 eight
 nine
 ten
 [root@yuji ~]# sed '5,8d' ff.txt    //删除第5~8行
 one
 two
 three
 four
 nine
 ten
 [root@yuji ~]# sed '$d' ff.txt     //删除最后一行
 one
 two
 three
 four
 five
 six
 seven
 eight
 nine
 [root@yuji ~]# sed 'd' ff.txt          //删除所有行
 [root@yuji ~]# sed '1,+3d' ff.txt      //删除第1行及后面3行(即删除第1~4行)
 five
 six
 seven
 eight
 nine
 ten
 [root@yuji ~]# sed '6,$d' ff.txt     //删除第6行到最后一行
 one
 two
 three
 four
 five
 [root@yuji ~]# sed '6!d' ff.txt      //除了第6行,其他都删除
 six
 [root@yuji ~]# sed '6,$!d' ff.txt    //除了第6行到最后一行,其他都删除
 six
 seven
 eight
 nine
 ten
复制代码

1.png

2.png

3.png

4.png

示例2:

通过字符串匹配出想要的行。

 [root@yuji ~]# sed '/e$/d' ff.txt    //删除以e结尾的行
 two
 four
 six
 seven
 eight
 ten
 [root@yuji ~]# sed '/e$/!d' ff.txt   //除了以e结尾的行,其他行都删除
 one
 three
 five
 nine
复制代码

5.png

示例3:

'/字符串1/,/字符串2/d' :从第一个匹配的位置打开删除功能,到第二个匹配的位置删完后关闭删除功能。之后继续按这个规则向下查找删除。

 [root@yuji ~]# cat 2.txt
 111
 222
 333
 444
 555
 111
 222
 333
 444
 555
 [root@yuji ~]# sed '/2/,/4/d' 2.txt  
 111
 555
 111
 555
 [root@yuji ~]# sed '/1/,/3/d' 2.txt
 444
 555
 444
 555
复制代码

6.png

示例4:

删除空行并保存:sed -i '/^$/d' file.txt (使用-i前先备份目标文件)

 [root@yuji ~]# cat file.txt
 11
 ​
 22
 ​
 33
 [root@yuji ~]# sed -i '/^$/d' file.txt
 [root@yuji ~]# cat file.txt
 11
 22
 33
复制代码

7.png

小贴士:

删除空行的三种方法:

  1. grep -v "^$" file.txt //过滤出非空行
  2. cat file.txt |tr -s "\n" //压缩换行符
  3. sed '/^$/d' file.txt //删除空行

6 sed 修改替换s c y

s:替换字符串

c:整行替换

y:字符替换,替换前后的字符串长度必须相同

6.1 替换字符串 s

格式:

 行范围 s/旧字符串/新字符串/替换标记
 ​
 #4种替换标记:
 数字:表明新字符串将替换第几处匹配的地方
 g:表面新字符串将会替换所有匹配的地方
 p:打印与替换命令匹配的行,与-n一起使用
 w 文件:将替换的结果写入文件中
复制代码

示例1:

[root@yuji ~]# sed -n '/root/p' pass.txt        //打印所有包含root的行
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@yuji ~]# sed -n 's/root/aaa/p' pass.txt       //将匹配行的第1个root替换成aaa
aaa:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/aaa:/sbin/nologin
[root@yuji ~]# sed -n 's/root/aaa/2p' pass.txt      //将匹配行的第2个root替换成aaa
root:x:0:0:aaa:/root:/bin/bash
[root@yuji ~]# sed -n 's/root/aaa/3p' pass.txt      //将匹配行的第3个root替换成aaa
root:x:0:0:root:/aaa:/bin/bash
[root@yuji ~]# sed -n 's/root/aaa/gp' pass.txt      //将匹配行的所有root替换成aaa
aaa:x:0:0:aaa:/aaa:/bin/bash
operator:x:11:0:operator:/aaa:/sbin/nologin
复制代码

1s1.png

示例2:

 [root@yuji ~]# sed -n 's/root//gp' pass.txt      //删除匹配行当所有root
 :x:0:0::/:/bin/bash
 operator:x:11:0:operator:/:/sbin/nologin
 [root@yuji ~]# echo 000010101 | sed 's/^0*//'    //删除开头所有的0
 10101
复制代码

1s2.png

示例3:

将root开头的行进行注释(在开头加上#);

在包含root的行的行尾加上#

 [root@yuji ~]# sed -n '/^root/p' pass.txt     //打印所有以root开头的行
 root:x:0:0:root:/root:/bin/bash
 [root@yuji ~]# sed -n '/^root/ s/^/#/p' pass.txt     //过滤出以root开头的行,在行首加上#
 #root:x:0:0:root:/root:/bin/bash
 ​
 [root@yuji ~]# sed -n '/root/p' pass.txt            //打印包含root的行
 root:x:0:0:root:/root:/bin/bash
 operator:x:11:0:operator:/root:/sbin/nologin
 [root@yuji ~]# sed -n '/root/ s/$/#/p' pass.txt     //在包含root的行的行尾加上#
 root:x:0:0:root:/root:/bin/bash#
 operator:x:11:0:operator:/root:/sbin/nologin#
复制代码

1s3.png

1s4.png

示例4:另一种替换方式

将包含root内容的行进行注释:

用正则表达式匹配包含root的整行内容,之后在整行内容前加#。&代表前面使用正则表达式匹配到的整行内容。

 [root@yuji ~]# sed -n '/root/ s/^/#/p' pass.txt     //过滤出包含root的行,在行首加上#
 #root:x:0:0:root:/root:/bin/bash
 #operator:x:11:0:operator:/root:/sbin/nologin
 [root@yuji ~]# sed -n 's/.*root.*/#&/p' pass.txt
 #root:x:0:0:root:/root:/bin/bash
 #operator:x:11:0:operator:/root:/sbin/nologin
复制代码

1s5.png

示例5:-f 指定脚本文件来执行

可以在文件中定义多条操作规则。

 [root@yuji ~]# vim 1.sh
 [root@yuji ~]# cat 1.sh
 /root/ s/^/#/p
 3,5 s/$/#/p
 ​
 [root@yuji ~]# sed -n -f 1.sh pass.txt       //指定1.sh文件来执行
 #root:x:0:0:root:/root:/bin/bash
 daemon:x:2:2:daemon:/sbin:/sbin/nologin#
 adm:x:3:4:adm:/var/adm:/sbin/nologin#
 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin#
 #operator:x:11:0:operator:/root:/sbin/nologin
复制代码

1s6.png

示例6:将修改后的内容保存到另一个文件中

1)重定向全文本(将修改后的行内容和原文其他内容一起保存)

 [root@yuji ~]# cat ff.txt
 one
 two
 three
 four
 five
 six
 seven
 eight
 nine
 ten
 [root@yuji ~]# sed '1,5 s/^/#/' ff.txt >out1.txt    //重定向全文本
 [root@yuji ~]# cat out1.txt
 #one
 #two
 #three
 #four
 #five
 six
 seven
 eight
 nine
 ten
复制代码

1s7.png

2)只重定向修改的内容(两种方法)

 #方法一,重定向
 [root@yuji ~]# sed -n '1,5 s/^/#/p' ff.txt >out2.txt
 [root@yuji ~]# cat out2.txt
 #one
 #two
 #three
 #four
 #five
 ​
 #方法二,使用w
 [root@yuji ~]# sed -n '1,5 s/^/#/w out3.txt' ff.txt
 [root@yuji ~]# cat out3.txt
 #one
 #two
 #three
 #four
 #five
复制代码

1s8.png

示例7:指定分隔符

当字符串中包含"/"时,需要在前面加上转义符\,避免和分隔符"/"混淆。这样操作非常麻烦,且容易眼花看错,此时可以自己指定分隔符。

s后面的第一个字符就是分隔符,3个分隔符要保持一致,如果遇到跟分隔符相同的字符需要使用 \ 转义成普通字符。

 #默认分隔符为"/"
 [root@yuji ~]# sed -n 's//bin/bash//sbin/nologin/p' pass.txt
 root:x:0:0:root:/root:/sbin/nologin
 yuji2:x:1000:1000:yuji2:/home/yuji2:/sbin/nologin
 nancy:x:1021:1021::/home/nancy:/sbin/nologin
 helen:x:1022:1022::/home/helen:/sbin/nologin
 ​
 #指定#作为分割符
 [root@yuji ~]# sed -n 's#/bin/bash#/sbin/nologin#p' pass.txt
 root:x:0:0:root:/root:/sbin/nologin
 yuji2:x:1000:1000:yuji2:/home/yuji2:/sbin/nologin
 nancy:x:1021:1021::/home/nancy:/sbin/nologin
 helen:x:1022:1022::/home/helen:/sbin/nologin
 ​
 #指定!作为分隔符
 [root@yuji ~]# sed -n 's!/bin/bash!/sbin/nologin!p' pass.txt
 root:x:0:0:root:/root:/sbin/nologin
 yuji2:x:1000:1000:yuji2:/home/yuji2:/sbin/nologin
 nancy:x:1021:1021::/home/nancy:/sbin/nologin
 helen:x:1022:1022::/home/helen:/sbin/nologin
 ​
 #指定8作为分隔符
 [root@yuji ~]# sed -n 's8/bin/bash8/sbin/nologin8p' pass.txt
 root:x:0:0:root:/root:/sbin/nologin
 yuji2:x:1000:1000:yuji2:/home/yuji2:/sbin/nologin
 nancy:x:1021:1021::/home/nancy:/sbin/nologin
 helen:x:1022:1022::/home/helen:/sbin/nologin
复制代码

1s9.png

1s10.png

思考:

 sed 's9\945\99\98\939g' test.txt  //这行命令的作用是什么?
 ​
 相当于s/94599/9893/g,指定了9作分隔符,那么普通的数字9前面要加\。即将94599替换成9893。
复制代码

1s11.png

6.2 整行替换 c

使用c进行替换,是对整行内容进行替换。

示例:

将包含字符串fo的行,整体替换成22。

 [root@yuji ~]# cat ff.txt
 one
 two
 three
 four
 five
 six
 seven
 eight
 nine
 ten
 [root@yuji ~]# sed '/fo/c 22' ff.txt    //将包含fo的行,整体替换成22
 one
 two
 three
 22
 five
 six
 seven
 eight
 nine
 ten
复制代码

2c.png

6.3 单字符替换 y

使用y,是对单个字符进行替换,每个字符需要一一对应,不是整体替换。前后字符串长度需要一致,不然会报错。

示例:

遇到n替换成2,遇到o替换成5。

 [root@yuji ~]# sed 'y/no/25/' ff.txt      //遇到n替换成2,遇到o替换成5
 52e
 tw5
 three
 f5ur
 five
 six
 seve2
 eight
 2i2e
 te2
 [root@yuji ~]# sed 'y/no/255/' ff.txt
 sed:-e 表达式 #1,字符 9:“y”命令的字符串长度不同
复制代码

3y.png

7 sed 增加a i r

a:在行后添加内容

i:在行前插入内容

r:在行后读入文件内容

7.1 在行后添加内容a

示例1:在第一行下方添加一行内容

 [root@yuji ~]# sed '1a 22' ff.txt      //在第一行下方添加一行内容
 one
 22222
 two
 three
 four
 five
 six
 seven
 eight
 nine
 ten
复制代码

1a1.png

示例2:在第1~3行,每行下方添加一行内容

 [root@yuji ~]# sed '1,3a 22' ff.txt     //在第1~3行,每行下方添加一行内容
 one
 22
 two
 22
 three
 22
 four
 five
 six
 seven
 eight
 nine
 ten
复制代码

1a2.png

示例3:在最后一行的下方,添加一行内容

 [root@yuji ~]# sed '$a 22' ff.txt     //在最后一行的下方,添加一行内容
 one
 two
 three
 four
 five
 six
 seven
 eight
 nine
 ten
 22
复制代码

1a3.png

示例4:在第一行下方添加3行内容

 [root@yuji ~]# sed '1a 22\n33\n44' ff.txt    //在第一行下方添加3行内容
 one
 22
 33
 44
 two
 three
 four
 five
 six
 seven
 eight
 nine
 ten
复制代码

1a4.png

7.2 在行前插入内容 i

示例:

 [root@yuji ~]# sed '1i 77' ff.txt        //在第一行的上方,添加一行内容
 77
 one
 two
 three
 four
 five
 six
 seven
 eight
 nine
 ten
 [root@yuji ~]# sed '1,3i 77' ff.txt      //在第1~3行每行的上方,添加一行内容
 77
 one
 77
 two
 77
 three
 four
 five
 six
 seven
 eight
 nine
 ten
复制代码

2i.png

7.3 在行后读入文件内容 r

示例:

 [root@yuji ~]# cat hh.txt
 hello world
 [root@yuji ~]# sed '6r hh.txt' ff.txt    //在第6行下方读入hh.txt文件内容
 one
 two
 three
 four
 five
 six
 hello world
 seven
 eight
 nine
 ten
复制代码

3r.png

8 sed 复制粘贴

比较vi/vim编辑器和 sed编辑器:

 #vi//vim编辑器:
 命令模式
 dd p  剪切 粘贴
 yy p  复制 粘贴
 
 末行模式
 :1,3 co 10  复制 粘贴(将第1~3行复制粘贴到第10行下方)
 :1,3 m 10   剪切 粘贴(将第1~3行剪切到第10行下方)
 ​
 #sed命令:
 H复制、d删除、G粘贴到指定行下方
复制代码

示例1:剪切粘贴

H复制,d删除,通过”复制后删除“来达到剪切的效果。

 [root@yuji ~]# sed '1,3 {H;d};$G' ff.txt     //将第1~3行剪切粘贴到最后一行下方
 four
 five
 six
 seven
 eight
 nine
 ten
 ​
 one
 two
 three
 [root@yuji ~]# sed '1,3 {H;d};5G' ff.txt     //将第1~3行剪切粘贴到第5行后面
 four
 five
 ​
 one
 two
 three
 six
 seven
 eight
 nine
 ten
复制代码

1.png

示例2:复制粘贴

将1到3行复制粘贴到最后一行后面。(注意中间会多出一行空行)

 [root@yuji ~]# sed '1,3 H;$G' ff.txt    //13行复制粘贴到最后一行后面
 one
 two
 three
 four
 five
 six
 seven
 eight
 nine
 ten
 ​
 one
 two
 three
复制代码

2.png

9 文件内容中的字符串进行互换

示例1:

 #将2个字符串交换位置
 [root@yuji ~]# echo 111222333
 111222333
 [root@yuji ~]# echo 111222333|sed -r 's/(111)(222)/\2\1/'
 222111333
 ​
 #将3个字符串交换位置
 [root@yuji ~]# echo 111222333|sed -r 's/(111)(222)(333)/\3\2\1/'
 333222111
 ​
 #将第一个字符和最后一个字符进行互换
 [root@yuji ~]# echo 111222333|sed -r 's/^(.)(.*)(.)$/\3\2\1/'
 311222331
复制代码

3交换位置1.png

3交换位置2.png

示例2:

将abc123修改成123abc、321cba。

 [root@yuji ~]# echo abc123| sed -r 's/(abc)(123)/\2\1/'
 123abc
 [root@yuji ~]# echo abc123| sed -r 's/(.)(.)(.)(.)(.)(.)/\6\5\4\3\2\1/'
 321cba
 [root@localhost ~]# echo abc123| sed -r 's/(a)(b)(c)(1)(2)(3)/\6\5\4\3\2\1/'
 321cba
复制代码

3交换位置3.png

10 总结

1、sed的核心功能:增删改查(可配合正则表达式)

 查: p
 ​
 删: d
 ​
 改: s(字符串替换)、c(整行替换)、y(对应字符进行替换,效果类似tr命令)
 ​
 增: i(在行前插入内容)、a(在行后添加内容)、r(在行后读入文件的内容)
 ​
 复制粘贴:H(复制)、d(删除)、G(粘贴到指定行下方)
复制代码

2、sed对指定行操作:

  • 以数字形式表示行区间
  • 用字符串来过滤行

3、 sed -i 可以直接修改文件内容,操作前建议先验证命令和备份目标文件 。

4、删除空行的三种方法:

 grep -v "^$"  file.txt        //过滤出非空行
 ​
 cat file.txt |tr -s "\n"      //压缩换行符
 ​
 sed  '/^$/d'  file.txt        //删除空行
复制代码

5、查找替换:

 行范围 s/旧字符串/新字符串/替换标记
 ​
 s/旧字符串/新字符串/2  #代表对每行第二个匹配到的字符串进行替换
                  g  #代表对每行所有能匹配到的字符进行替换
                  p  #可以结合-n 选项只打印替换的行内容
                  w  #可以把替换的行内容保存到指定的文件中
                  
 n,m s/旧字符串/新字符串/       #指定第n行到第m行,将旧字符串替换成新字符串
 ​
 /字符串+正则/ s/旧字符串/新字符串/    #过滤出想要的行,之后进行替换
 ​
 s/^/添加的字符/    #行首添加内容
 ​
 s/$/添加的字符/    #行尾添加内容
 ​
 sed -f 文件    #指定脚本文件来执行,可以在文件中定义多条操作规则
 ​
 sed指定字符串的分隔符,就看s后面跟的字符,3个分隔符要保持一致,如果遇到跟分隔符相同的字符则需要使用\来转义。
 例如:s#/bin/bash#/sbin/nologin#g