文本三剑客之sed编辑器

208 阅读7分钟

sed编辑器

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

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

sed编辑器的工作流程

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

读取:sed从输入流(文件、管道、标注输入)中读取一行内容并存储到临时的缓冲区中(又称模式空间,pattern space)

执行:默认情况下,所有的sed命令都在模式空间中顺序的执行,除非指定了行的地址,否则sed命令将会在所有的行上依次执行

显示:发送修改的内容到输出流,在发送数据后,模式空间将会被清 空,在所有的文件内容都被处理完成之前,上述过程将重复执行,直至 所有内容被处理完

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

注意∶ 默认情况下所有的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 文件2 ...

常用选项

选项作用
-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 对指定行进行操作

sed编辑器有两种寻址方式:

1.以数字形式表示行区间

2.用文件模式(字符串)来过滤出行(一般结合正则表达式)

数字形式表示行区间

指定行打印

sed -n '1p' testfile1    ##只打印第一行内容
sed -n '$p' testfile1    ##打印最后一行内容
sed -n '1,3p' testfile1   ##打印1-3行内容
sed -n '1,+3p' testfile1   ##打印第一行内容和连续三行内容
sed '5q' testfile1        ##q表示退出,5q表示打印五行之后退出

Snipaste_2022-09-05_18-59-13.png

打印奇数行和偶数行

sed -n 'p;n' testfile1  ## n:移动到下一行,打印奇数行
sed -n 'n;p' testfile1  ##打印偶数行

Snipaste_2022-09-05_19-00-45.png

打印间隔行(一行或者多行)

sed -n '2,${n;p}' testfile1   ##打印从第二行开始到最后一行打印奇数行

Snipaste_2022-09-05_19-05-03.png

用文件模式(字符串)来过滤出行

过滤文本所在的行

sed -n '/root/p' /etc/passwd  ##过滤出包含root的行
sed -n '/^l/p' /etc/passwd    ##过滤出以l开头的行
sed -n '/n$/p' /etc/passwd     ##过滤出以n结尾的行
sed -n '/mail|games/p' /etc/passwd  ##过滤出以mail开头或者以games结尾的行   |是特殊字符需要在前面加\
​
sed -n '2,/rpcbind/p' /etc/passwd ##打印从第一个包含2的行到第一个包含rpcbind行之间的所有行 
Snipaste_2022-09-05_19-10-36.png Snipaste_2022-09-05_19-19-12.png

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

sed -rn '/r.{1,}t/p' /etc/passwd  ##

Snipaste_2022-09-05_19-22-37.png

sed 删除行

删除指定行内容

sed '3d' test ##删除第三行内容
sed '1,3d' test ##删除1-3行内容

Snipaste_2022-09-05_19-33-37.png

删除包含指定内容的行

sed '/^s/d' testfile1   ##删除以s开头的行
sed '/en$/d' testfile1  ##删除以en为结尾的行
sed '/en$/!d' testfile1 ##!表示取反,删除除以en结尾的所有行
sed '/2/,/3/d' testfile1  ##从第一个包含2的行开始删,删到第一个包含3的行  第一位置打开删除功能,第二位置关闭删除行功能 容易发生误删操作
Snipaste_2022-09-05_22-00-38.png Snipaste_2022-09-05_22-01-52.png Snipaste_2022-09-05_22-03-11.png

删除空行的三种方法

sed '/^$/d' test  ##删除空行
grep -v "^$" file.txt ##过滤出非空行
cat file.txt |tr -s "\n" ##压缩换行符
Snipaste_2022-09-05_22-06-18.png

修改替换s c y

格式

行范围 s/旧字符串/新字符串/替换标记

替换标记

数字:表明新字符串将替换第几处匹配的地方

g:表明新字符串将会替换所有匹配的地方

p:打印与替换命令匹配的行,与**-n**一起使用

w文件:将替换的结果写入文件中

替换指定字符,并指定替换第几处或者替换所有(替换所有用g)

sed -n 's/root/aaa/p' /etc/passwd  ##将匹配行的第1个root替换成aaa
sed -n 's/root/aaa/gp' /etc/passwd //将匹配行的所有root替换成aaa

Snipaste_2022-09-05_22-11-02.png

替换空值,表示删除

sed -n 's/root//gp' /etc/passwd  ##将匹配

Snipaste_2022-09-05_22-13-46.png

添加注释 删除注释

sed -n '/^root/ s/^/#/p' /etc/passwd    ##过滤出以root开头的行,在行首加上#
​
sed -n '/^root/ s/^//' /etc/passwd    ##删除注释

Snipaste_2022-09-05_22-18-45.png

另一种替换方式

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

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

sed -n 's/.*root.*/#&/p' /etc/passwd

Snipaste_2022-09-05_22-22-52.png

-f 指定脚本文件来执行

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

[root@localhost demo]#cat 1.sh 
/root/ s/^/#/p
3,5 s/^/#/p
[root@localhost demo]#sed -n -f 1.sh /etc/passwd
#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

Snipaste_2022-09-05_22-25-29.png

将所有字母改成大写字母

s/[a-z]/\u&/g  小写转大写
s/[A-Z]/\l&/g  大写转小写
s/\a[a-z]/\u&/g  首字母小写转大写

Snipaste_2022-09-05_22-29-12.png

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

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

Snipaste_2022-09-05_22-34-12.png

指定分隔符

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

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

整行替换C

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

sed '/fo/c 22' testfile1

Snipaste_2022-09-05_22-52-42.png

单字符转化 y

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

sed 'y/no/12' testfile1

Snipaste_2022-09-05_22-55-57.png

插入内容

a:在行后添加内容

sed '1,3a 123' testfile1 ##在第1~3行,每行下方添加一行内容

Snipaste_2022-09-05_22-58-36.png

i:在行前插入内容

sed '3i 123' testfile1  ##在第3行上面添加一行内容

Snipaste_2022-09-05_23-00-56.png

r:在行后读入文件内容

sed '6r hh.txt' testfile1

Snipaste_2022-09-05_23-03-40.png

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粘贴到指定行下方

剪切粘贴

H复制,d删除,G粘贴到指定行下方

sed '1,3{H;d};$G' testfile1 ##将1-3行内容剪切粘贴到最后一行

Snipaste_2022-09-05_23-07-29.png

复制粘贴

sed '1,3H;$G' testfile1 ##将1-3行复制粘贴到最后一行后面
Snipaste_2022-09-05_23-09-35.png

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

#将3个字符串交换位置
 [root@yuji ~]# echo 111222333
 111222333
 [root@yuji ~]# echo 111222333 | sed -r 's/(111)(222)(333)/\3\2\1/'
 222111333

Snipaste_2022-09-05_23-12-39.png

echo abc | sed -r 's/^(.)(.)(.)$/\3\2\1/' ##将字母交换位置

Snipaste_2022-09-05_23-13-47.png

将abc123修改成123abc、321cba

echo abc123| sed -r 's/(abc)(123)/\2\1/' ##将abc123修改成123abc
echo abc123| sed -r 's/(.)(.)(.)(.)(.)(.)/\6\5\4\3\2\1/'  将abc123修改成321cba

Snipaste_2022-09-05_23-16-16.png