Linux 文本三剑客 - Sed
Stream EDitor(sed)是一种行编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为模式空间(pattern space),接着用 sed 命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。然后读入下行,执行下一个循环。如果没有使诸如 'D' 的特殊命令,那会在两个循环之间清空模式空间,但不会清空保留空间。这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。
参考:http://www.gnu.org/software/sed/manual/sed.html
1、Sed 命令
sed [option]… 'script' inputfile… option: -n 不输出模式空间内容到屏幕,即不自动打印 -e 多点编辑 -f 从指定文件中读取编辑脚本 -r 支持使用扩展正则表达式 -i.bak 备份文件并原处编辑 script: 地址定界: 1> 不给地址: 对全文进行处理 2> 单地址 /pattern/: 被此处模式所能匹配到的每一行 3> 地址范围 # 10,+20 表示第 10 行到第 10+20=30 行 /pat1/,/par2/ #,/pat1/ 4> 步进: ~ 1~2 奇数行 2~2 偶数行 编辑命令: d: 删除模式空间匹配的行,并立即启用下一轮循环 p: 打印当前模式空间内容,追加到默认输出之后(默认打印,p 打印两边) a [\]text: 在指定行后面追加文本 i [\]text: 在行前面插入文本 c [\]text: 替换行为单行或多行文本 w /path/somefile: 保存模式匹配的行至指定文件 r /path/somefile: 读取指定文件的文本至模式空间中 扩展正则表达式 匹配到的行后: =: 为模式空间中的行打印行号 !: 模式空间中匹配行取反处理
2、Sed 编辑命令
2.1 打印
编辑命令(p)打印当前模式空间内容,追加到默认输出之后,通常和 sed -n
一起使用。
打印指定行:
"默认打印 + 指定行打印" [root@aliyunhost ~]# df -h | sed '2p' Filesystem Size Used Avail Use% Mounted on /dev/vda1 40G 18G 20G 47% / /dev/vda1 40G 18G 20G 47% / devtmpfs 910M 0 910M 0% /dev tmpfs 920M 0 920M 0% /dev/shm tmpfs 920M 97M 824M 11% /run tmpfs 920M 0 920M 0% /sys/fs/cgroup tmpfs 184M 0 184M 0% /run/user/0 "sed -n,关闭默认打印" [root@aliyunhost ~]# df -h | sed -n '2p' /dev/vda1 40G 18G 20G 47% / "打印出第一行和第三行" [root@aliyunhost ~]# df -h | sed -n -e '1p' -e '3p' Filesystem Size Used Avail Use% Mounted on devtmpfs 910M 0 910M 0% /dev
打印特定行:
"打印奇数行" [root@aliyunhost ~]# sed -n '1~2p' /etc/passwd "打印偶数行" [root@aliyunhost ~]# sed -n '2~2p' /etc/passwd
搜索打印:
"打印以root开头的行" [root@aliyunhost ~]# sed -n '/^root/p' /etc/passwd root:x:0:0:root:/root:/bin/bash "打印以b开头的行~以h开头的行" [root@aliyunhost ~]# sed -n '/^b/,/^h/p' /etc/passwd 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:/bin/false sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt
2.2 删除
编辑命令(d)用于删除模式空间匹配的行。
实例:
"测试的文件" [root@aliyunhost ~]# cat demo.txt 1 2 3 4 5 6 "删除第二行" [root@aliyunhost ~]# sed '2d' demo.txt 1 3 4 5 6 "打印发现并没有真正删除掉" [root@aliyunhost ~]# cat demo.txt 1 2 3 4 5 6 "使用 sed -i 编辑文件" [root@aliyunhost ~]# sed -i '2d' demo.txt [root@aliyunhost ~]# cat demo.txt 1 3 4 5 6 "恢复测试文件" [root@aliyunhost ~]# cat demo.txt 1 2 3 4 5 6 "删除并备份" [root@aliyunhost ~]# sed -i.bak '2,6d' demo.txt [root@aliyunhost ~]# cat demo.txt 1 [root@aliyunhost ~]# cat demo.txt.bak 1 2 3 4 5 6
2.3 插入
编辑命令(a, i)分别表示在指定行后面、前面插入文本。
在指定行前插入文本:
[root@aliyunhost ~]# cat demo.txt python java golang erlang "在java行之后插入" [root@aliyunhost ~]# sed -i '/java/ajavascript' demo.txt [root@aliyunhost ~]# cat demo.txt python java javascript golang erlang "如果匹配到多行,则会插入多次" [root@aliyunhost ~]# sed -i '/^java/ashell' demo.txt [root@aliyunhost ~]# cat demo.txt python java shell javascript shell golang erlang "a后面也可以使用反斜杠和插入的内容隔开" [root@aliyunhost ~]# sed -i '/^g/a\role' demo.txt [root@aliyunhost ~]# cat demo.txt python java shell javascript shell golang role erlang
在指定行后插入文本:
[root@aliyunhost ~]# cat demo.txt python java golang "在python行之前插入" [root@aliyunhost ~]# sed -i '/^p/ijavascript' demo.txt [root@aliyunhost ~]# cat demo.txt javascript python java golang "如果匹配到多行,则会插入多次" [root@aliyunhost ~]# sed -i '/^j/ishell' demo.txt [root@aliyunhost ~]# cat demo.txt shell javascript python shell java golang "i后面也可以使用反斜杠和插入的内容隔开" [root@aliyunhost ~]# sed -i '/^g/i\erlang' demo.txt [root@aliyunhost ~]# cat demo.txt shell javascript python shell java erlang golang
2.4 替换
编辑命令(c)用于替换搜索行为目标行。
实例:
[root@aliyunhost ~]# cat demo.txt python java shell javascript shell golang role erlang "替换匹配行" [root@aliyunhost ~]# sed -i '/^e/c\xxxxxx' demo.txt [root@aliyunhost ~]# cat demo.txt python java shell javascript shell golang role xxxxxx
2.5 读入或输出指定文件
编辑命令(w)用于将保存模式匹配的行输出至指定文件。
[root@aliyunhost ~]# cat -n demo.txt 1 python 2 java 3 shell 4 javascript 5 erlang "将demo.txt的第2~4行输出至test.txt" [root@aliyunhost ~]# sed '2,4w test.txt' demo.txt python java shell javascript erlang [root@aliyunhost ~]# cat test.txt java shell javascript
编辑命令(r)用于读取指定文件的文本至模式空间中。
[root@aliyunhost ~]# cat test.txt java shell [root@aliyunhost ~]# cat demo.txt python javascript erlang "将test.txt文件中的内容插入到demo.txt文件第三行后面" [root@aliyunhost ~]# sed -i '3r test.txt' demo.txt [root@aliyunhost ~]# cat demo.txt python javascript erlang java shell
2.6 搜索替代
编辑命令 s/source_str/target_str/[替换标记]
支持搜索匹配内容并替换。支持正则(sed -r)、支持分组。
替换标记(g):行内全局替换
替换标记(p):显示替换成功的行
替换标记(w /PATH/TO/SOMEFILE):将替换成功的行保存至文件中
实例:
[root@aliyunhost ~]# cat selinux # This file controls the state of SELinux on the system. # SELINUX= can take one of these three values: # enforcing - SELinux security policy is enforced. # permissive - SELinux prints warnings instead of enforcing. # disabled - No SELinux policy is loaded. SELINUX=enforcing # SELINUXTYPE= can take one of three two values: # targeted - Targeted processes are protected, # minimum - Modification of targeted policy. Only selected processes are protected. # mls - Multi Level Security protection. SELINUXTYPE=targeted "打印" [root@aliyunhost ~]# sed -nr 's/(SELINUX=)([a-z]{1,})/\1disabled/p' selinux SELINUX=disabled "替换" [root@aliyunhost ~]# sed -i -r 's/(SELINUX=)([a-z]{1,})/\1disabled/g' selinux [root@aliyunhost ~]# cat selinux # This file controls the state of SELinux on the system. # SELINUX= can take one of these three values: # enforcing - SELinux security policy is enforced. # permissive - SELinux prints warnings instead of enforcing. # disabled - No SELinux policy is loaded. SELINUX=disabled # SELINUXTYPE= can take one of three two values: # targeted - Targeted processes are protected, # minimum - Modification of targeted policy. Only selected processes are protected. # mls - Multi Level Security protection. SELINUXTYPE=targeted
3、Sed 高级编辑命令
高级编辑命令:(模式空间、保持空间)
P:打印模式空间开端至\n 内容,并追加到默认输出之前
h:把模式空间中的内容覆盖至保持空间中
H:把模式空间中的内容追加至保持空间中
g:从保持空间取出数据覆盖至模式空间
G:从保持空间取出内容追加至模式空间
x:把模式空间中的内容与保持空间中的内容进行互换
n:读取匹配到的行的下一行覆盖至模式空间
N:读取匹配到的行的下一行追加至模式空间
d:删除模式空间中的行
D:如果模式空间包含换行符,则删除直到第一个换行符的模式空间中的文本,并会读取新的输入行,而使用合成的模式空间重新启动循环。如果模式空间不包含换行符,则会像发出 d 命令那样启动正常的新循环。
实例:
[root@aliyunhost ~]# seq 10 | sed -n 'n;p' 2 4 6 8 10 [root@aliyunhost ~]# seq 10 | sed '1!G;h;$!d' 10 9 8 7 6 5 4 3 2 1 [root@aliyunhost ~]# seq 10 | sed 'N;D' 10 [root@aliyunhost ~]# seq 10 | sed '$!N;$!D' 9 10 [root@aliyunhost ~]# seq 10 | sed '$!d' 10 [root@aliyunhost ~]# seq 10 | sed 'G' 1 2 3 4 5 6 7 8 9 10 [root@aliyunhost ~]# seq 10 | sed 'g' [root@aliyunhost ~]# seq 10 | sed '/^$/d;G' 1 2 3 4 5 6 7 8 9 10 [root@aliyunhost ~]# seq 10 | sed 'n;d' 1 3 5 7 9 [root@aliyunhost ~]# seq 10 | sed -n '1!G;h;$p' 10 9 8 7 6 5 4 3 2 1