Sed 全称 Stream editor,一个流线式的非交互式的编辑器。它每次读取一行放入模式空间缓冲区中,直到全部命令都执行完后把结果送往屏幕,而后读取下一行。由于是将输入内容复制到缓冲区处理,因此不会对原文件有任何影响,若是须要保存处理后的结果能够重定向生成新的文件。linux
本文全部示例均基于txt.log文件,其中增长了行号。具体内容以下:bash
1 root:x:0:0:root:/root:/bin/bash 2 bin:x:1:1:bin:/bin:/sbin/nologin 3 daemon:x:2:2:daemon:/sbin:/sbin/nologin 4 adm:x:3:4:adm:/var/adm:/sbin/nologin 5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin 6 sync:x:5:0:sync:/sbin:/bin/sync 7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown 8 halt:x:7:0:halt:/sbin:/sbin/halt 9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin 10 uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin 11 operator:x:11:0:operator:/root:/sbin/nologin 12 games:x:12:100:games:/usr/games:/sbin/nologin 13 gopher:x:13:30:gopher:/var/gopher:/sbin/nologin 14 ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin 15 nobody:x:99:99:Nobody:/:/sbin/nologin 16 dbus:x:81:81:System message bus:/:/sbin/nologin 17 vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin 18 abrt:x:173:173::/etc/abrt:/sbin/nologin 19 haldaemon:x:68:68:HAL daemon:/:/sbin/nologin 20 ntp:x:38:38::/etc/ntp:/sbin/nologin 21 saslauth:x:499:76:"Saslauthd user":/var/empty/saslauth:/sbin/nologin 22 postfix:x:89:89::/var/spool/postfix:/sbin/nologin 23 sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin 24 tcpdump:x:72:72::/:/sbin/nologin 25 nscd:x:28:28:NSCD Daemon:/:/sbin/nologin
定址即指定sed 处理的范围,默认是输入内容的每一行。有两种方式:行号和正则。具体见下表ssh
Sed 定址方式详解tcp
选项 | 含义 | 备注 |
---|---|---|
x | 第x行 | sed -n '3p' /etc/passwd 输出第3行 |
$ | 最后一行,固定写法 | sed -n '$p' /etc/passwd |
x~Nth | 从第x行开始,返回每隔N行的 | sed -n '1~2p' /etc/passwd 输出奇数行 |
x,y | x 到 y 之间的行(包含x和y) | sed -n '1,3p' /etc/passwd 输出1到3行 |
/pattern/ | 查询包含模式的行 | sed -n '/dae/p' /etc/passwd 打印含有dae的行 |
/pattern/,/pattern/ | 包含两个模式间的 | sed -n '/root/, /mail/p' /etc/passwd |
/pattern/,x | 模式跟行号间的 | sed -n '/root/, 10p /etc/passwd |
x,/pattern/ | 行号跟模式间的 | sed -n '1,/da/p' /etc/passwd |
addr1, +N | 从开始位置起的后N行 | sed -n -e '1, +3p' -e /etc/passwd |
x,y! | 除了x,y 以外的全部行 | !表示在前边条件知足后,直接取反 |
行号或者单个模式的容易理解,再也不赘述。下边着重演示两个模式及行号与模式混用的细节。归纳讲,模式在前边,则进行屡次匹配直到最后一行;若是在后边,只发生一次匹配,若无匹配到有效行则默认处理到最后一行。先找出包含root 和 daemon的行,代码以下: 编辑器
sed -n '/root/p' txt.log #找出包含root的行 ##====================== # 1 root:x:0:0:root:/root:/bin/bash # 11 operator:x:11:0:operator:/root:/sbin/nologin ##====================== sed -n '/daemon/p' txt.log #找出包含daemon的行 ##====================== # 3 daemon:x:2:2:daemon:/sbin:/sbin/nologin # 19 haldaemon:x:68:68:HAL daemon:/:/sbin/nologin ##====================== sed -n '/mail/p' txt.log #找出包含mail的行 ##====================== # 9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin ##======================
#找出包含root到daemon之间的行 sed -n '/root/,/daemon/p' txt.log ##========================== # 分析可知root有两行(1,11),daemon有两行(3,19) # 匹配到第一行后,找daemon 在第三行,因此先输出1,3行 # 因为起始的模式会屡次匹配,则发起第二次查找11行,因此返回11-19行 # 从20行后继续找root,一直到最后一行,没有了,退出 ##========================== #依据上述分析,查出/daemon/ 和 /mail/之间的行,结果是什么呢 sed -n '/daemon/, /mail/p' txt.log ##========================== # 返回的结果是3-9行和19-25行 # daemon(3,19),,mail(19),txt.log 共25行 # sed -n '/mail/, /daemon/p' txt.log 返回哪些行呢,为何? ##==========================
#起始为模式时总会返回模式匹配的行 sed -n '/root/, 8p' txt.log #输出1-8与11行 sed -n '/mail/, 8p' txt.log #输出第9行
sed -n '2, /daemon/p' txt.log #输出2-3行,以最早找到的daemon为准 sed -n '10,/mail/p' txt.log #输出10-25行,mail(9) 10行后未匹配,直到最后一行,
选项 | 释义 | 示例 |
---|---|---|
-n | 配合p命令使用,只打印匹配的行 | sed -n '1,3p' txt.log 不加n是输出因此行与匹配行 |
-e | 用于执行多个命令 | sed -n -e '/root/p' -e '/root/=' txt.log |
-i | 直接修改文件内容 | sed -i '/root/Root/s' txt.log |
-r | 支持扩展正则 |
#匹配行后新加一行 sed '/root/anewafter' txt.log sed '10,$/anewafter' txt.log #匹配行前新加一行 sed '/root/inewbefore' txt.log sed '10,$/inewbefore' txt.log
#删除匹配的行,行内的删除用替换实现 sed '/root/d' txt.log
替换命令有三个:s,c,y功能略有差别,另外在讲缓冲区时,也会涉及另外一种替换实现。post
#c 表示将匹配的全部行的内容替换成新的字符串 sed -i '/^SELINUX=/c\SELINUX=disabled' /etc/selinux/config sed '1,10chello' txt.log #将1-10行的内容替换为hello #y 一对一替换,字符数必须相等且不支持正则,不然报错 sed '1,10y/r/R/' txt.log # 将1-10行的小写r 换成大写R #s 支持正则 ##======================= # 支持元字符正则 # 分组\(..\) s/\(love\)able/\1rs/ 最多到\9 # & 保存搜索字符 s/love/**&**/ 将love 替换成 **love** # \< /> 匹配单词开始和结尾 # \{m,n\} 支持限定符 ##======================= sed '1,10s/^.*$/#&/' txt.log #1-10行开头加上# sed 's/^/#/' txt.log ##======================= # 跟s配合的命令 # p 打印 sed 's/r/R/p' 能够结合-n选项使用 # g 替换每行全部出现的 sed -n 's/r/R/gp' # N 替换每行第N个 sed -n 's/r/R/2p' # w 将结果写入文件 sed 's/r/R/w output' txt.log ##======================= sed -n '1,10s/r/R/p' txt.log #把1-10行的r换成大写,每行的第一个 sed -n 's/\([Rr]\)oot/\1OOT/gpw output.res' txt.log
#将结果写入新文件 w sed '1,5w head5.log' txt.log #匹配的1-5行写入head5.log且所有输出到屏幕 #从文件里读取 r sed '/root/r head5.log' txt.log #在匹配行后加上从文件中读取的内容 #退出命令q 表示完成指定地址匹配后当即退出 sed '/root/ q' txt.log #匹配到第一个root 后当即退出 #显示控制字符 l sed -n 'l' txt.log #打印出含有控制字符的行 #输出文件行号 = sed -n '/root/=' txt.log #打印出匹配的行号
包括多命令执行,缓冲区读写实现的移动和替换功能等。spa
##=============== # 多命令有三种方式 sed -e '' -e '' 上边说过 # 大括号{命令1;命令2} 如 sed -n '/root/{p;=}' # 分号间隔多个命令 '命令1;命令2' 如 sed 's/r/R/;s/b/B/' ##=============== sed -e 's/R/r/' -e 's/o/O/g' txt.log sed 's/R/r/;s/o/O/g' txt.log sed -n '/root/{s/R/r/;s/o/O/}' txt.log #处理匹配行的下一行 n sed -n '/root/{n;s/r/R/g;}' sed '/root/{n;y/b/B/;}' txt.log #{}中最后一条命令的分号不能省 ##=============== # 模式缓冲区和保持缓冲区 # 命令h和H 将模式缓冲区的内容放到保持缓冲区 h 是覆盖 H是追加 # 命令g和G 将保持缓冲区的内容放到模式缓冲区 g 是覆盖 G是追加 # x 互换模式缓冲区和保持缓冲区的内容 # 通常用于移动文本内部的行或是用某行替换某行 ##=============== sed '/root/h;/daemon/G' txt.log #将离daemon前边的最后的一个root 行追加到 daemon后边 sed '/root/h;/daemon/x;' txt.log #将daemon行替换为前边最后的一条root 行
为了强化记忆,基于txt.log 的内容提出了几个题目,分A,B,C 三级,欢迎在评论区亮出你的答案,想看标准答案别忘了打赏,看到后私信给你 :) ,再偷偷的告诉你一句,只要仔细看完教程,答案不在话下!3d
sed 强化练习code
A级 |
---|
1. 打印出偶数行 sed -n '2~2p' txt.log 或 sed '1~2d' txt.log |
2. 打印出不包含数字3或5的行 sed -n '/[35]/!p' txt.log |
3. 在含有大写字母行的下边插入一空行,并将结果保存成blank_line.log sed '/[A-Z]/a\\n' txt.log > blank_line.log |
4. 删除blank_line.log全部的空行并保存 sed -i '/^$/d' blank_line.log |
B级 |
1. 删除每行第一个字母前的全部字符并保存为 nonu.log sed -n 's/\([^A-Za-z]\{1,\}\)//pw none_num.log' txt.log |
2. 将包含root的首行开头加上#,其它行不做处理 sed '/root/{s/^/#/;q;}' txt.log |
3. 将全部的非零的一位数字前补零 sed -n 's/\<\([1-9]\{1\}\)\>/0\1/gp' txt.log |
C级 |
1. 删除含有root行下的连续3行 sed '/root/, +3d' txt.log |
2. 互换包含root 和 daemon的行 |