文本三剑客sed流编辑器

122 阅读8分钟

sed流编辑器

sed 是一种在线的非交互式的编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区
中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容
送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。
Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。

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

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

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

注意:默认情况下所有的sed命令都是在模式空间内执行的,因此输入的文件并不会发生任何变化,除非是用重定向存储输出

buffer 缓冲使用内存空间 写的操作

cache 缓存使用内存空间 读的操作

命令格式

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"选项一起使用
=打印行号
i(小写L)打印数据流中的文本和不可打印的ABCII字符(比如结束符$,制表符\t)

sed增删改查 1

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

sed命令应用

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

sed -e 'p':会打印两次

[root@localhost mm]# sed -e 'p' 3.txt   //-e会打印两次
one
one
two
two
three
three
four
four
five
five
six
six
seven
seven
eight
eight
nine
nine
ten
ten

sed -n -e 'p':跳过显示过程,所以每行内容只会显示一次

[root@localhost mm]# sed -n -e 'p' 3.txt   //-n跳过显示过程,所以每行内容只会显示一次
one
two
three
four
five
six
seven
eight
nine
ten

sed -n '=' :打印行号

[root@localhost mm]# sed -n '=' 3.txt  //打印行号
1
2
3
4
5
6
7
8
9
10

sed -e '=':打印行号与内容

[root@localhost mm]# sed -e '=' 3.txt  //打印行号与内容
1
one
2
two
3
three
4
four
5
five
6
six
7
seven
8
eight
9
nine
10
ten
[root@localhost mm]# sed -n '=;p' 3.txt   //括号里面加上一个分号,就可以实现多命令
1
one
2
two
3
three
4
four
5
five
6
six
7
seven
8
eight
9
nine
10
ten

sed -n 'l': l 代表结束符$ ,制表符\t

[root@localhost mm]# sed -n 'l' 3.txt  //l代表结束符$   ,制表符\t
one$
two$
three$
four$
five$
six$
seven$
eight$
nine$
ten$

执行多命令的方法

#方法一  
sed -n -e '=' -e 'p' file.txt  ​

#方法二
sed -n -e '=;p' file.txt  ​

#方法三:换行操作  
sed -n'  
^=
^p  
^' file.txt

用数字来显示行

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

单行打印

[root@localhost mm]# sed -n '1p' 3.txt  //只显示第一行
one
[root@localhost mm]# sed -n '3p' 3.txt   //只显示第三行
three

多行打印

[root@localhost mm]# sed -n '1,3p' 3.txt  //显示第一行到第三行
one
two
three
[root@localhost mm]# sed -n '6,$p' 3.txt  //显示第六行到最后一行
six
seven
eight
nine
ten
[root@localhost mm]# sed -n '1,+3p' 3.txt  //打印第一行以及它之后的连续三行内容(如同1-4行一样)
one
two
three
four

打印五行的方法


[root@localhost mm]# sed '5q' 3.txt  //打印五行后退出(相当于1-5行)
one
two
three
four
five

[root@localhost mm]# sed -n '1,5p' 3.txt
one
two
three
four
five

[root@localhost mm]# sed -n '1,+4p' 3.txt
one
two
three
four
five

打印奇数,偶数行

sed -n 'p;n':读取下一行,奇数

sed -n 'n;p':偶数

[root@localhost mm]# sed -n 'p;n' 3.txt  //P打印输出并,n读取下一行内容(循环所以会输出奇数)
one
three
five
seven
nine

[root@localhost mm]# sed -n 'n;p' 3.txt
two
four
six
eight
ten

sed -n '2,${n;p}' //从第三行打印一直到奇数行

[root@localhost mm]# sed -n '2,${n;p}' 3.txt  //从第三行打印一直到奇数行
three
five
seven
nine

通过字符串来过去文本

打印包含six字符串的行内容

[root@localhost mm]# sed -n '/six/p' 3.txt  //打印包含six字符串的行内容
six

打印包含root的行内容

[root@localhost mm]# grep 'root' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

[root@localhost mm]# sed -n '/root/p' /etc/passwd  //打印包含root的行内容
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

运用正则表达式打印

运用正则表达式查看以root开头的行内容
[root@localhost mm]# sed -n '/^root/p' /etc/passwd
root:x:0:0:root:/root:/bin/bash

运用正则表达式查看以bash结尾的行内容
[root@localhost mm]# sed -n  '/bash$/p' /etc/passwd
root:x:0:0:root:/root:/bin/bash
w:x:1000:1000:w:/home/w:/bin/bash
wangwu:x:1001:1001::/home/wangwu:/bin/bash
shangsan:x:1002:1002::/home/shangsan:/bin/bash
zhuliu:x:1003:1003::/home/zhuliu:/bin/bash
laoba:x:1004:1004::/home/laoba:/bin/bash
laoliu:x:1005:1005::/home/laoliu:/bin/bash
liangliang:x:1006:1006::/home/liangliang:/bin/bash
jiujiu:x:1007:1007::/home/jiujiu:/bin/bash
baibai:x:1008:1008::/home/baibai:/bin/bash

-r与 \

[root@localhost mm]# sed -n '/mail|games/p' /etc/passwd   //要使用 | 必须要加上-r才能打印出来

[root@localhost mm]# sed -nr '/mail|games/p' /etc/passwd
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin

[root@localhost mm]# sed -n '/mail\|games/p' /etc/passwd   //不想加-r的话可以使用\来打印
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
[root@localhost mm]# sed -n '/mail\|games/p' /etc/passwd
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
[root@localhost mm]# sed -n '/nobody/=' /etc/passwd
13
35



[root@localhost mm]# sed -n '2,/nobody/p' /etc/passwd   
//从第二行开始一直到第一个包含nobody的行打印出来(相当于就是从第二行到十三行)
bin:x:1:1:bin:/bin:/sbin/nologin
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
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
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
[root@localhost mm]# sed -n '2,/nobody/=' /etc/passwd
2
3
4
5
6
7
8
9
10
11
12
13

[root@localhost mm]# sed -rn '/r.{1,}t/p' /etc/passwd  //显示包含r和t中间有任意字符的打印出来
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
polkitd:x:999:997:User for polkitd:/:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
libstoragemgmt:x:998:995:daemon account for libstoragemgmt:/var/run/lsm:/sbin/nologin
saslauth:x:996:76:Saslauthd user:/run/saslauthd:/sbin/nologin
setroubleshoot:x:995:993::/var/lib/setroubleshoot:/sbin/nologin
rtkit:x:172:172:RealtimeKit:/proc:/sbin/nologin
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
gnome-initial-setup:x:991:986::/run/gnome-initial-setup/:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin

sed删除行

[root@localhost mm]# sed 'd' 3.txt  //全部删除

[root@localhost mm]# sed '1d' 3.txt  //删除第一行
two
three
four
five
six
seven
eight
nine
ten

[root@localhost mm]# sed '$d' 3.txt  //删除最后一行
one
two
three
four
five
six
seven
eight
nine
[root@localhost mm]# sed '1,3d' 3.txt  //删除一到三行
four
five
six
seven
eight
nine
ten

[root@localhost mm]# sed '4,$d' 3.txt  //删除第四行到最后一行
one
two
three

sed '/^s/d':删除以s开头的行

[root@localhost mm]# sed '/^s/d' 3.txt  //删除以s开头的行
one
two
three
four
five
eight
nine
ten
[root@localhost mm]# sed '/en$/d' 3.txt   //删除以en结尾的行
one
two
three
four
five
six
eight
nine

!号取反

[root@localhost mm]# sed '/en$/!d' 3.txt  //出了以en结尾的都删除
seven
ten

删除空行的方法

[root@localhost mm]# grep -v "^$" 3.txt
one
two
three
four
five
six
seven
eigh
nine
ten


[root@localhost mm]# cat 3.txt |tr -s '\n'
one
two
three
four
five
six
seven
eigh
nine
ten


[root@localhost mm]# sed '/^$/d' 3.txt
one
two
three
four
five
six
seven
eigh
nine
ten


[root@localhost mm]# sed -n '/^$/!p' 3.txt  //反向删除
one
two
three
four
five
six
seven
eigh
nine
ten
[root@localhost mm]# sed '/2/,/5/d' 4.txt  //删除从第一个包含2的行到第一个包含5的行
1
5
444
555
1000
165
85
555
666
166
999
888

[root@localhost mm]# sed '/1/,/5/d' 4.txt 
//从第一个位置打开删除功能,到第二个位置关闭删除功能
5
444
555
85
555
666

删除空行的三种方法:

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

sed替换

s:替换字符串

c:整行替换

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

替换字符串格式:

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

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

应用

[root@localhost mm]# sed -n '/root/p' /etc/passwd  //查找包含root的行
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

[root@localhost mm]# sed -n 's/root/admin/p' /etc/passwd  //把root换成admin
admin:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/admin:/sbin/nologin
[root@localhost mm]# sed -n '/^root/ s/root/admin/p' /etc/passwd   //更换以root开头的行并把root替换成admin,默认只更换匹配到的第一行
admin:x:0:0:root:/root:/bin/bash

[root@localhost mm]# sed -n '/^root/ s/root/admin/2p' /etc/passwd  //替换第二个root
root:x:0:0:admin:/root:/bin/bash

[root@localhost mm]# sed -n '/^root/ s/root/admin/gp' /etc/passwd  //g是代表所有的
admin:x:0:0:admin:/admin:/bin/bash

[root@localhost mm]# sed -n '/^root/ s/root//gp' /etc/passwd
//匹配包含root的行,将root替换成空格
:x:0:0::/:/bin/bash
[root@localhost mm]# sed '1 s/^/#/' 3.txt  //给行首加上注释符
#one
two
three
four
five
six
seven
eigh
nine
ten

[root@localhost mm]# sed '1,5 s/^/#/' 3.txt  //一到五行加上注释符号
#one
#two
#three
#four
#five
six
seven
eigh
nine
ten
[root@localhost mm]# sed '/^#f/ s/#//' 3.txt  //删除以#f开头的注释
#one
#one
#two
#two
#three
#three
four
four
five
five
six
seven
eigh
nine
ten

大小写的转换

[root@localhost mm]# echo abcdefgh | tr a-z A-Z
ABCDEFGH

sed -f  脚本文件
s/ [a-z] /\u& / g  小写转大写
s/ \b [ a-z]/\u& / g  首字母小写转大写
s/[A-zj/\l&/g   大写转小写