Sed 简介
sed是一种新型的,非交互式的编辑器。它能执行与编辑器vi 和 ex相同的编辑任务。sed编辑器没有提供交互式使用方式,使用者只能在命令行输入编辑命令、指定文件名,然后在屏幕上查看输出。sed 编辑器没有破坏性,它不会修改文件,除非使用 shell重定向来保存输出结果。默认情况下,所有的输出行都被打印到屏幕上。
sed工作过程
sed编辑器逐行处理文件(或输入),并将输出结果发送到屏幕。sed的命令就是在 vi和ed/ex 编辑器中见到的那些。 sed 把当前正在处理的行保存在一个临时缓存区中,这个缓存区称为模式空间或临时缓冲。sed处理完模式空间中的行后(即在该行上执行sed 命令后),就把改行发送到屏幕上(除非之前有命令删除这一行或取消打印操作)。sed 每处理完输入文件的最后一行后, sed 便结束运行。 sed 把每一行都存在临时缓存区中,对这个副本进行编辑,所以不会修改或破坏源文件。如图 1:sed 处理过程。
从上图可以看出sed不是破坏性的,它不会修改正在编辑的文件。
Sed 命令格式
1
|
sed
命令行格式为:
sed
[选项] ‘
command
’ 输入文本
|
Sed定位
Sed命令在没有给定的位置时,默认会处理所有行;
Sed 支持一下几种地址类型:
1、 first~step
这两个单词的意思: first 指起始匹配行, step 指步长,例如: sed -n 2~5p 含义:从第二行开始匹配,隔 5 行匹配一次,即 2,7,12.......。
2、 $
这个$符表示匹配最后一行。
3、 /REGEXP/
这个是表示匹配正则那一行,通过//之间的正则来匹配。
4、 \cREGEXPc
这个是表示匹配正则那一行,通过\c 和 c 之间的正则来匹配,c可以是任一字符
5、 addr1,add2
定址addr1,add2 决定用于对哪些行进行编辑。地址的形式可以是数字、正则表达式或二者的结合。如果没有指定地址,sed 将处理输入文件中的所有行。如果定址是一个数字,则这个数字代表行号,如果是逗号分隔的两个行号,那么需要处理的定址就是两行之间的范围(包括两行在内)。范围可以是数字,正则或二者组合。
6、addr1,+N
从addr1这行到往下 N 行匹配,总共匹配 N+1 行
7、 addr1,~N
Will match addr1 and the lines following addr1 until the next line whose input line number is a multiple of N.【没有看懂是什么意思】
Sed的正则表达式
表1:sed的正则表达式元字符
元字符 | 功 能 | 示 例 | 示例的匹配对象 |
^ | 行首定位符 | /^love/ | 匹配所有以 love 开头的行 |
$ | 行尾定位符 | /love$/ | 匹配所有以 love 结尾的行 |
. | 匹配除换行外的单 个字符 |
/l..e/ | 匹配包含字符 l、后跟两个任意 字符、再跟字母 e 的行 |
* | 匹配零个或多个前 导字符 |
/*love/ | 匹配在零个或多个空格紧跟着 模式 love 的行 |
[] | 匹配指定字符组内 任一字符 |
/[Ll]ove/ | 匹配包含 love 和 Love 的行 |
[^] | 匹配不在指定字符 组内任一字符 |
/[^A-KM-Z]ove/ | 匹配包含 ove,但ove之前的那 个字符不在 A 至 K 或 M 至 Z 间 的行 |
\(..\) | 保存已匹配的字符 | ||
& | 保存查找串以便在 替换串中引用 |
s/love/**&**/ | 符号&代表查找串。字符串love 将替换前后各加了两个**的引 用,即 love 变成**love** |
\< | 词首定位符 | /\<love/ | 匹配包含以 love 开头的单词的 行 |
\> | 词尾定位符 | /love\>/ | 匹配包含以 love 结尾的单词的 行 |
x\{m\} | 连续 m 个 x | /o\{5\}/ | 分别匹配出现连续 5 个字母 o、 至少 5 个连续的 o、或 5~10 个 连续的 o 的行 |
x\{m,\} | 至少 m 个 x | /o\{5,\}/ | |
x\{m,n\} | 至少 m 个 x,但不 超过 n 个 x |
/o\{5,10\}/ |
sed的常用选项
表2.sed的常用选项
选项 | 说明 |
-n | 使用安静模式,在一般情况所有的 STDIN 都会输出到屏幕上,加入-n 后只打印 被 sed 特殊处理的行 |
-e | 多重编辑,且命令顺序会影响结果 |
-f | 指定一个 sed 脚本文件到命令行执行, |
-r | Sed 使用扩展正则 |
-i | 直接修改文档读取的内容,不在屏幕上输出 |
Sed 操作命令
sed 操作命令告诉 sed 如何处理由地址指定的各输入行。如果没有指定地址, sed 就会处理输入的所有的行。表 3.sed 命令
命 令 | 说 明 |
a\ | 在当前行后添加一行或多行 |
c\ | 用新文本修改(替换)当前行中的文本 |
d | 删除行 |
i\ | 在当前行之前插入文本 |
h | 把模式空间里的内容复制到暂存缓存区 |
H | 把模式空间里的内容追加到暂存缓存区 |
g | 取出暂存缓冲区里的内容,将其复制到模式空间,覆盖该处原有内容 |
G | 取出暂存缓冲区里的内容,将其复制到模式空间,追加在原有内容后面 |
l | 列出非打印字符 |
p | 打印行 |
n | 读入下一输入行,并从下一条命令而不是第一条命令开始处理 |
q | 结束或退出 sed |
r | 从文件中读取输入行 |
! | 对所选行意外的所有行应用命令 |
s | 用一个字符串替换另一个 |
表 4.替换标志
g | 在行内进行全局替换 |
p | 打印行 |
w | 将行写入文件 |
x | 交换暂存缓冲区与模式空间的内容 |
y | 将字符转换为另一字符(不能对正则表达式使用 y 命令) |
报错信息和退出信息
遇到语法错误时, sed 会向标准错误输出发送一条相当简单的报错信息。但是,如果 sed判断不出错在何处,它会“断章取义”,给出令人迷惑的报错信息。如果没有语法错误, sed将会返回给 shell 一个退出状态,状态为 0 代表成功,为非 0 整数代表失败。
案例:
sed -n '1p' passwd 只打印第一行
ifconfig eth1 |sed -n 2p
seq 100 |sed -n '1~2p'步进,只显示奇数行
seq 100 |sed -n '2~2p'步进,只显示偶数行
sed -i.orig 's/dog/cat/g' pets 备份后再替换
sed '2a\dog cat dog cat cat' pets 在第二行后增加新行
sed '2i\dog cat dog cat cat' pets 在第二行前增加新行
sed '2c\dog cat dog cat cat' pets 替换第二行
sed '2w /path/filename' pets 将第二行保存到指定文件
sed '2r /path/filename' pets 将指定文件读取并加到第二行后
sed '=' pets 在显示的结果前显示行号
sed -n 'n;p' FILE
显示偶数行
sed '1!G;h;$!d' FILE
逆向显示文件内容
sed 'N;D' FILE
仅显示最后一行
sed '$!N;$!D' FILE
仅显示文件最后两行
sed '$!d' FILE
仅保留最后一行
sed ‘G’ FILE
每行后加一个空行
sed ‘g’ FILE
将每行内容替换为空行
sed ‘/^$/d;G’ FILE
每行后加一个空行,已有空白行的,仅显示一个空白行
sed 'n;d' FILE
显示奇数行
sed -n '1!G;h;$p' FILE
逆向显示文件内容
习题:
1、删除/etc/grub2.conf文件中所有以空白开头的行行首的空白字符
[root@centos7 ~]# sed -r 's@^[[:space:]]\+@@' /etc/grub2.cfg
2、删除/etc/fstab文件中所有以#开头,后面至少跟一个空白字符的行的行首的#和空白字符
[root@centos7 ~]# sed -r 's@^#[[:space:]]+@@' /etc/fstab
3、在/etc/fstab每一行行首增加#号
- [root@centos7 ~]# sed -e 's@^@#&@' -e 's@^$@#@' /etc/fstab
或者
[root@centos7 ~]# sed 's@^.*@#&@' /etc/fstab
注意:此处不可写成sed 's@^(.*)@#$@' /etc/fstab,这是错误的,此处锚定的是(),而不是行首
空白行锚定使用^$
[root@centos7 ~]# cat > f1
()
a
b
^C
[root@centos7 ~]# sed 's@^(.*)@#&@' f1
#()
a
b
4、在/etc/fstab文件中不以#开头的行的行首增加#号
[root@centos7 ~]# sed 's@^[^#]@#&@' /etc/fstab
5、处理/etc/fstab路径,使用sed命令取出其目录名和基名
[root@centos7 ~]# echo /etc/fstab | sed -r 's@(.*/)([^/]+/?$)@\1@'
/etc/
[root@centos7 ~]# echo /etc/fstab | sed -r 's@(.*/)([^/]+/?$)@\2@'
fstab
6、利用sed 取出ifconfig命令中本机的IPv4地址
[root@centos7 ~]# ifconfig | sed -n '2p' | sed -e 's@.*inet[[:space:]]@@' -e 's@[[:space:]].*@@'
或者
[root@centos7 ~]# ifconfig | sed -n '2p' | sed -r 's@.*inet[[:space:]](.*)[[:space:]]net.*@\1@'
10.1.0.17
当然,如果使用cut就简单多了
[root@centos7 ~]# ifconfig | sed -n '2p' | tr -s ' ' | cut -d' ' -f3
10.1.0.17
7、统计centos安装光盘中Package目录下的所有rpm文件的以.分隔倒数第二个字段的重复次数
[root@centos7 Packages]# ls | grep "rpm$" | sed -e 's@.rpm$@@' -e 's@.*\.@@' | sort | uniq -c
2000 i686
2938 noarch
4069 x86_64
或者
[root@centos7 Packages]# ls | grep "rpm$" | sed -r 's@.*\.(.*)\.rpm@\1@' | sort | uniq -c
2000 i686
2938 noarch
4069 x86_64
8、统计/etc/init.d/function中每个单词的重复次数,并倒序排列
- [root@centos7/etc/yum.repos.d]#cat /etc/init.d/functions | tr -c '[:alpha:]' '\n' | tr -s '\n' | sort | uniq -c | sort -nr
注意常见的错误
使用正则表达式注意.的转义
使用扩展正则表达式注意分组时要加-r
再或者
[root@centos7 Packages]# ls | grep "rpm$" | rev | cut -d. -f2 | sort | uniq -c总结:个人认为,sed命令是grep命令的延伸,虽然有些功能比如筛选同样的行时,俩者都可实现,但是如果数据量很大的话,相比而言,grep是更加方便的。所以grep筛选数据,sed再处理数据,这样无疑是最好的结果。至于截取特定的字段的话,cut、tr、grep和sed同样都可以实现,而sed又无疑是这三个里面最强大的(分组截取字段),所以这些要勤加练习,才能掌握的游刃有余。
4069 46_68x
2000 686i
2938 hcraon