sed命令总结
张贺,多年互联网工作经验,担任过网络工程师、系统集成工程师、LINUX系统运维工程师
笔者微信:zhanghe15069028807
1、概述
sed
的作用我们就记得两条就可以了:替换和增删改查,也就是说今后当我们想对文件进行一些文字的替换和增删改查时就要想起sed
。
sed
的语法分成三部分,我们来举一个例子:
//sed <选项-n> <对谁操作,3代表第3行> <干啥p,p代表打印> <要操作的文件>
sed -n 3p /etc/passwd
sed的执行过程:
将文件"吸入"内存,然后在内存里面处理,处理好之后将空间内的内容倾倒到屏幕。
sed常用的选项其实就三个最为常用:
-n:仅显示处理的行
-r:使其支持扩展的正则表达式
-i:sed默认不改变文件的内容,使用-i会改变文件的内容,慎用!
-e:-e选项允许在同一行里执行多条命令(不好用)
2、查
1、打印整行(一或多)
1、显示文件的哪一行,或是哪几行,要求我们提示知道要显示的东西哪几一行,如果不知道想要的行在文件是第几行,那么可以先用cat -n
或是less -N
进行查看确认,然后再用sed
打印。
//通过这个例子体会`-n`这个选项的作用
[root@zabbix3 tmp]# cat test.txt
zhanghe
zhangjia
zhangwei
[root@zabbix3 tmp]# sed 2p test.txt
zhanghe
zhangjia
zhangjia
zhangwei
[root@zabbix3 tmp]# sed -n 2p test.txt
zhangjia
[root@zabbix3 tmp]# cat test.txt
zhanghe
zhangjia
zhangwei
//仅打印最后一行
[root@zabbix3 tmp]# sed -n '2p' test.txt
zhangjia
//打印最后一行
[root@zabbix3 tmp]# sed -n '$p' test.txt
zhangwei
//下面这两个例子效果是一样的
[root@zabbix3 tmp]# sed -n '2,3p' test.txt
zhangjia
zhangwei
[root@zabbix3 tmp]# sed -n '2,+1p' test.txt
zhangjia
zhangwei
2、正则打印包含关键字的行
2、我们想要显示出现某个关键字的行,比如找出/etc/passwd
当中开头是zhanghe
关键字的行,我们就得使用正则表达式进行匹配,在sed
当中一旦想要使用正则表达式的话就要使用//
这两个符号,在这两上符号内部写正则表达式。
//其实不用sed,通过grep实现这个需求更简单,不是吗?如下所示:
[root@zabbix3 ~]# grep "^zhanghe" /etc/passwd
zhanghe:x:1000:1000::/home/zhanghe:/bin/bash
//下面是这是通过sed实现的,看着还麻烦一点
[root@zabbix3 ~]# sed -n '/^zhanghe/p' /etc/passwd
zhanghe:x:1000:1000::/home/zhanghe:/bin/bash
// 显示结尾是/bin/bash的行
[root@zabbix3 ~]# grep '/bin/bash$' /etc/passwd
root:x:0:0:root:/root:/bin/bash
zhanghe:x:1000:1000::/home/zhanghe:/bin/bash
//下面是这是通过sed实现的
[root@zabbix3 ~]# sed -n '/\/bin\/bash$/p' /etc/passwd
root:x:0:0:root:/root:/bin/bash
zhanghe:x:1000:1000::/home/zhanghe:/bin/bash
显示开头是root
或者zhanghe
的行
//“|”符号属于扩展的正则,所以sed加r,grep加e
[root@zabbix3 ~]# egrep '^(root|zhanghe)' /etc/passwd
root:x:0:0:root:/root:/bin/bash
zhanghe:x:1000:1000::/home/zhanghe:/bin/bash
[root@zabbix3 ~]# sed -rn '/^(root|zhanghe)/p' /etc/passwd
root:x:0:0:root:/root:/bin/bash
zhanghe:x:1000:1000::/home/zhanghe:/bin/bash
打印出开头是root
行一直到结尾nologin
的中间的行,我们还是可以使用正则表达式
[root@localhost ~]# sed -n '/^root/,/nologin$/p' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
其实用正则表达式匹配范围非常适合我们用来查看日志,假如说我们查看一下某个时间点到另一个时间点之间发生了什么事情?如下所示:
[root@localhost ~]# sed -n '/Oct 21 15:42:48/,/Oct 21 16:09:26/p' /var/log/secure
2、增
增常常于查连用,而查无非是根据行号和正则表达式查询,一定要体会到这个联系!才会把sed的查和增联系起来
我们在文本后面增加东西有几种方法呢?vim、nano、>>(echo 、cat)
除了这些方法之后,在文本里面增加内容也只有sed了。
通过sed在文本里面增加内容实际上非常的简单,主要就用到三个选项:a/i/c。
a:
apped
在匹配到的行下面加i:
insert
在匹配到的行上面加r:在行的后面加内容,加的内容必须来自于文件
c:把这一行内容替换成你想要的内容 #看着是不是有点熟悉,grep也有类似的选项
y:作用字符替换,将匹配的内容做替换
w:将匹配到的行输出到另一个文件
//在文本的第3行下面添加两行内容
[root@localhost ~]# sed '3azhanghe\nzhanghe' /etc/passwd zhanghe,zhanghe
//在开头是root的行下面添加两行内容zhanghe,zhanghe
[root@localhost ~]# sed '/^root/azhanghe\nzhanghe' /etc/passwd
//把第一行整体替换成zhanghe,这是替换的一整行
[root@localhost ~]# sed '1czhanghe' /etc/passwd | head -2
zhanghe
bin:x:1:1:bin:/bin:/sbin/nologin
//在/etc/passwd文件里面匹配到以root开头的行,然后这一行的下一行添加/tmp/text.txt里面的内容
sed '/^root/r /tmp/text.txt' /etc/passwd
//把text.txt文件里面包括my的行放置到text2.txt里面,注意这里面的顺序
sed -n '/my/w test2.txt' test.txt
将前10行当中的所有小写的s转换成大写的S和将全文所有小写的s转成大写的S
sed '1,10y/s/S/' /etc/passwd
3、删
删除最简单的了,就是使用一个局部命令d就可以了,如下所示:
//删除第一行
sed '1d' /tmp/passwd
//删除1、2、3行
sed '1,3d' /etc/passwd
//删除开头的root的行一直到结尾是nologin的行
sed '/^root/,/nologin$/d' /tmp/passwd
//删除开头是#号的行
sed '/^#/d' /etc/nginx/nginx.conf
//删除真空行
sed '/^$/d' /etc/nginx/nginx.conf
//删除带空格的假空行(平时记住这个即可)
sed '/^[[:space:]]*$/d' /etc/nginx/nginx.conf
4、替换
在sed的替换功能这里面我们要对替换做一个总结,文本的替换有很多方法,我们来总结一下,当前讲的sed的通用替换方式即:s@@@
这种方式, 这种方式是通用的查找到什么就能替换什么,灵活强大,某字符的替换、大小写的替换皆可做,但是整行的替换通过s@@@
不太好做,需要用到二级命令c
//字符替换(词语、单个字符)
sed 's@root@R00T@g' /etc/passwd
sed '1,10y/s/S/' /etc/passwd
tr 's' 'S' < /etc/passwd
//大小写的转换,u和l代表和upper和lower
sed 's@[a-z]@\u&@g' file
sed 's@[A-Z]@\l&@g' file
tr '[a-z]' '[A-Z]' < /etc/passwd
tr '[[:lower:]]' '[[:upper:]]' < /etc/passwd
//整行替换,将第二行无论什么内容都替换成888
sed 2c888 /etc/passwd
替换是sed
最重要的功能,也比较简单,我们只需要记住sed替换的标准格式,即:
//s是`sub`的意思,g是`global`就是全局的意思,整体意思就是全局替换。
sed 's@@@g'
[root@localhost tmp]# cat test.txt
zhanghe
zhangmin
zhangjia
zhanghe
zhanghezhanghe
// 不加g,只会替换第一行
[root@localhost tmp]# sed 's@zhanghe@hello@' test.txt
hello
zhangmin
zhangjia
hello
hellozhanghe
//加上g就是全局替换
[root@localhost tmp]# sed 's@zhanghe@hello@g' test.txt
hello
zhangmin
zhangjia
hello
hellohello
其实g所在的位置指代的是哪几代,g是指全部嘛,如果写一个3那就是第三列,也就是说我们可以指定替换哪一列当中的字符串,如下所示,我们替换第三列当中的zhanghe
为hello
:
[root@localhost tmp]# cat test.txt
zhanghe
zhangmin
zhangjia
zhanghe
zhanghezhanghe
zhanghe
//#只有第三列变化了,第一列和第二列的zhanghe都没有被替换
[root@localhost tmp]# sed 's@zhanghe@hello@3' test.txt
zhanghe
zhangmin
zhangjia
zhanghe
zhanghezhanghe hello #注意,这是按照词语进行替换的,我们上面讲的-c选项是按行进行替换的。
在替换当中,只有第一个条件可以使用模式,第二个不可以
[root@zhanghe ~]# cat zh.txt
i like
on,my,love
[root@zhanghe ~]# sed 's#\(l..e\)#\1r#' zh.txt #把l..e替换成l..er
i liker
on,my,lover
[root@zhanghe ~]# sed 's#l\(..e\)#L\1#' zh.txt #仅把l..e的l替换成大写
i Like
on,my,Love
//利用sed命令把history开始的空白字符给删除了
history | sed 's@^[[:space:]]*@@'
history | sed 's@^[[:space:]]\+@@g'
history|sed 's#^[[:space:]]\{3\}##g'
5、后向引用
所谓的后向引用就是将想要引用的东西用括号包起来,如果再用到的话就可以直接调用了,就是这么简单。
[root@localhost tmp]# echo 123456 | sed -r 's@(.*)@\1@g' #.*就代表所有
123456
[root@localhost tmp]# echo 123456 | sed -r 's@1234(.*)@\1@g' #这个所有指代的就是5和6
56
//取IP
[root@zabbix3 ~]# ifconfig eth0 | sed -n 2p
inet 192.168.80.199 netmask 255.255.255.0 broadcast 192.168.80.255
[root@zabbix3 ~]# ifconfig eth0 | sed -n 2p | sed -r 's@^.*et (.*) net.*@\1@'
192.168.80.199
6、结合
同时执行多条sed
语句,-e选项允许在同一行里执行多条命令
//先将第2行到最后一行给删除了,只留下第一行,然后将第一行的ROOT替换成TTTTT
sed -e '2,$d' -e 's@ROOT@TTTTT@' /etc/passwd
7、练习
删除/etc/grub.conf
文件中行首的空白字符(提示:替换)
[root@zhanghe ~]# sed 's@^[[:space:]]@@' /etc/grub.conf
替换/etc/inittab
文件当中的id:3:initdefault:
一行当中的数字为5(提示:后向引用)
[root@A ~]# sed "s%^id:[0-9]:initdefault:$%id:5:initdefault:%" /etc/inittab
[root@China ~]# sed "s@\(id:\)[0-9]\(:initdefault:\)@\15\2@g" /etc/inittab
sed "s@\(id:\)[[:digit:]]\(:initdefault:\)@\16\2@" /etc/inittab
sed -r -i "s@(id:)[[:digit:]](:initdefault:)@\16\2@" /etc/inittab
删除/etc/inittab
文件当中的空白行(提示:删除)
[root@China ~]# sed "/^[[:space:]]*$/d" /tmp/grub.conf
删除/etc/inittab
文件当中以#开头的行(提示:删除)
[root@zhanghe ~]# sed "/^#/d" /etc/inittab
删除某文件中开头的#及后面的空白字符的行,但要求#号后面必须有空白字符(提示:删除)
[root@zhanghe ~]# sed "/^#[[:space:]]/d" test.sh
删除某文件中以空白字符后面跟#号的行中开头的空白字符及#(提示:删除)
[root@zhanghe ~]# sed "s@^[[:space:]]\+#@@" test.sh
取出一个文件路径的目录名称(后向引用)
[root@China ~]# echo "/etc/sysconfig" | sed 's@[^/]\+$@@'
/etc/
[root@China ~]# echo "/etc/sysconfig/" | sed 's@[^/]\+$@@'
/etc/sysconfig/
[root@China ~]# echo "/etc/rc.d" | sed -r "s@^(/.*/)[^/]+/?@\1@g"
/etc/
[root@China ~]# echo "/etc/rc.d" | sed -r "s@[^/]+/?\$@@g"
/etc/
解析:第一回是在线开头的字符至少出现一次,并且还要在词尾给删了,删除之后可不就剩下斜线开头的目录了嘛,但是,如果目录是一个绝对路径呢?就像
echo /zhang/he/ | sed "s@\(\/[[:alnum:]]\+\/\)\([[:alnum:]]\+\/\?\)@\1@"
/zhang/
echo /zhang/he/ | sed "s@\(\/[[:alnum:]]\+\/\)\([[:alnum:]]\+\/\?\)@\2@"
he/
取出一个目录的基名和目录名()
[root@China ~]# basename /etc/sysconfig
sysconfig
[root@China ~]# dirname /etc/sysconfig
/etc
把/etc/fstab当中空行和开头是空格的、开头是#号都删除掉(提示:删除)
//把/etc/fstab当中空行和开头是空格的、开头是#号都删除掉
sed 's@^#@@' /etc/fstab | sed '/^[[:space:]]*$/d' | sed 's@^[[:space:]]@@'
//把/etc/fstab当中空行和开头是空格的、开头是#号的行都删除掉,注意,上面是删除字,实质是替换,这里是删行
sed '/^#/d' test.txt | sed '/^[[:space:]]/d' | sed '/^[[:space:]]*$/d'
打印奇数或偶数行
sed -n 'p;n' <file> #打印奇数行
sed -n 'n;p' <file> #打印偶数行
打印完前三行后,退出sed
[root@zhanghe ~]# sed '3q' /etc/passwd
ROOT:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
将文件当中所有的字母转成大写
最好的办法不是使用sed而是使用tr,如果tr命令的话是这样:
tr 'a-z' 'A-Z' < file
将文件当中前10的abcde转成为大写
sed '1,10y/abcde/ABCDE/' /etc/passwd
将前10行当中的所有小写的s转换成大写的S和将全文所有小写的s转成大写的S
sed '1,10y/s/S/' /etc/passwd
sed 's@s@S@g' /etc/passwd
8、进阶
是否真正理解了sed是一个行编辑器?
sed是一个行编辑器,行编辑器的意思是只能一行行的处理,比如你可以删除任意行,但不能删除某一行当中的某一个字段,如下所示:
//删除第二行
[root@n9 ~]# cat -n /etc/issue
1 \S
2 Kernel \r on an \m
3
[root@n9 ~]# cat -n /etc/issue | sed 2d
1 \S
3
//删除第二行当中on单词,是无法删除的,无法删除的原因并不是没有匹配上,而是做不到,
[root@n9 ~]# cat -n /etc/issue | sed -n 2p | sed '/on/d'
2 Kernel \r on an \m
//通过grep我们可以确定最后一个sed是一定是匹配到了on,但sed删除功能的细粒度只是行而已,做不到仅删除字符串。
在使用替换s@A@B@
格式的时候,第一次匹配,也就是A处的匹配一定要把一整行全都匹配上,不能仅仅匹配一行当中的某个或某些字段,这么说有些抽象,我们用例子来说明:
[root@n9 ~]# ifconfig eth0 | sed -n 2p
inet 192.168.80.59 netmask 255.255.255.0 broadcast 192.168.80.255
[root@n9 ~]# ifconfig eth0 | sed -n 2p | sed -r 's@^.*inet (.*) netmask@\1@'
192.168.80.59 255.255.255.0 broadcast 192.168.80.255
[root@n9 ~]# ifconfig eth0 | sed -n 2p | sed -r 's@^.*inet (.*) netmask.*@\1@'
192.168.80.59
[root@n9 ~]# ifconfig eth0 | sed -n 2p | sed -r 's@^.*inet (.*) netmask@\1@'
192.168.80.59 255.255.255.0 broadcast 192.168.80.255
上面这个为什么会出错呢?不是因为扩展的正则表达式写错了,那我怎么肯定我没有写错呢?通过egrep就可以确定,我把sed使用的扩展正则表达式^.*inet (.*) netmask
放到egrep里面,就能看见到底匹配到了哪些内容,如下所示,内容并没有匹配错:
[root@n9 ~]# ifconfig eth0 | egrep -o '^.*inet (.*) netmask'
inet 192.168.80.59 netmask
//这条命令到底错了哪里?
[root@n9 ~]# ifconfig eth0 | sed -n 2p | sed -r 's@^.*inet (.*) netmask@\1@'
192.168.80.59 255.255.255.0 broadcast 192.168.80.255
如上所示,在s@^.*inet (.*) netmask@\1@
正则表达式当中,(.*)
匹配的内容并不仅仅匹配的是inet
后面的内容和netmask
前面的内容,(.*)
的真正的含义是匹配除了^.*inet
匹配到的,和除了netmask
这个单词之外内容,结果就是就把192.168.80.59 255.255.255.0 broadcast 192.168.80.255
给匹配出来了。
解决办法我们上面说过了,只要在第一次匹配的时候把要处理的行匹配完整,就不会有这种情况发生,也就是在netmask
后面加上.*
,这样就把一行匹配完整了,下面举几个例子:
[root@n9 ~]# ifconfig eth0 | sed -n 2p | sed -r 's@^.*inet (.*) netmask.*@\1@'
192.168.80.59
ip addr show eth0 | sed -n 3p
inet 192.168.80.59/24 brd 192.168.80.255 scope global noprefixroute eth0
ip addr show eth0 | sed -n 3p | sed -r 's@[[:space:]]+inet (.*) brd@\1@'
192.168.80.59/24 192.168.80.255 scope global noprefixroute eth0
ip addr show eth0 | sed -n 3p | sed -r 's@[[:space:]]+inet (.*) brd.*@\1@'
192.168.80.59/24
ip addr show eth0 | sed -n 3p | sed -r 's@[[:space:]]+inet (.*) (\bbrd\b.*eth0$)@\1@'
192.168.80.59/24
sed命令总结的更多相关文章
- 文本处理三剑客之sed命令
第十八章.文本处理三剑客之sed命令 目录 sed介绍 sed命令常用选项 sed常用编辑命令 sed使用示例 sed高级语法 18.1.sed简介 sed全名stream editor,流编辑器,s ...
- linux shell 用sed命令在文本的行尾或行首添加字符
转自 http://www.cnblogs.com/aaronwxb/archive/2011/08/19/2145364.html 昨天写一个脚本花了一天的2/3的时间,而且大部分时间都耗在了sed ...
- linux sed命令详解
简介 sed 是一种在线编辑器,它一次处理一行内容.处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的 ...
- sed命令详解
搜索 纠正错误 添加实例 sed 功能强大的流式文本编辑器 补充说明 sed 是一种流编辑器,它是文本处理中非常中的工具,能够完美的配合正则表达式使用,功能不同凡响.处理时,把当前处理的行存储在临时 ...
- Linux安全基础:sed命令的使用
sed 是一个很好的文件处理工具,本身是一个管道命令,主要是以行为单位进行处理,可以将数据行进行替换.删除.新增.选取等特定工作. Sed本质上是一个编辑器,但是它是非交互式的,这点与VIM不同:同时 ...
- [转]sed命令详解
转载:http://blog.chinaunix.net/u/22677/showart_1076318.html 1.简介 sed是非交互式的编辑器.它不会修改文件,除非使用shell重定向来保 ...
- sed命令
sed是一个很好的文件处理工具,本身是一个管道命令,主要是以行为单位进行处理,可以将数据行进行替换.删除.新增.选取等特定工作,下面先了解一下sed的用法sed命令行格式为: sed ...
- sed 命令使用
ios 的sed 命令 跟linux sed 命令有区别 # 所有的a 替换成b sed -i "" 's/a/b/g' #删除掉所有包含a的行 sed -i "/a/ ...
- sed命令给文本文件的每行的行首或者行尾添加文字
在每行的头添加字符,比如"HEAD",命令如下: sed 's/^/HEAD&/g' test.file 在每行的行尾添加字符,比如“TAIL”,命令如下: sed 's/ ...
- Linux的sed命令
一.初识sed 在部署openstack的过程中,会接触到大量的sed命令,比如 # Bind MySQL service to all network interfaces.sed -i 's/12 ...
随机推荐
- 痞子衡嵌入式:恩智浦i.MX RTxxx系列MCU开发那些事 - 索引
大家好,我是痞子衡,是正经搞技术的痞子.本系列痞子衡给大家介绍的是恩智浦i.MX RTxxx系列微控制器相关知识. 恩智浦半导体于2018年10月发布的i.MX RTxxx系列开启了ML/AI MCU ...
- C#实现地图坐标系的转换(WGS-84、GCJ-02、BD-09)
WGS-84坐标系:全球定位系统使用,GPS.北斗等 GCJ-02坐标系:中国地区使用,由WGS-84偏移而来 BD-09坐标系:百度专用,由GCJ-02偏移而来 (PS:源于项目需求,本来是想读图 ...
- sklearn集成支持向量机svm.SVC参数说明
经常用到sklearn中的SVC函数,这里把文档中的参数翻译了一些,以备不时之需. 本身这个函数也是基于libsvm实现的,所以在参数设置上有很多相似的地方.(PS: libsvm中的二次规划问题的解 ...
- Docker 私服Registry简介与使用Docker-Compose安装Registry
场景 Docker-Compose简介与Ubuntu Server 上安装Compose: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/deta ...
- 网站后台getshell
phpmyadmin后台Getshell 获取 web 绝对路径 select @@basedir; 检测是否有写入权限 show global variables like 'secure%' ## ...
- PHP 生成 UUID 函数
Generate name based md5 UUID (version 3) /** * Generate name based md5 UUID (version 3). * @example ...
- java 报错 System.out.printIn 错误: 找不到符号
java 运行 System.out.printIn() 报错 ,java System.out.println 这是错误示范 !!! System.out.printIn("仔细看看pri ...
- C# WPF 解决方案MineRealms启动器 自动随机播放音乐的代码
//Nothing //Nothing string[] files = Directory.GetFiles(Path.GetDirectoryName(App.config.MainConfigP ...
- mysql DDL 锁表
mysql DDL 锁表 select trx_state, trx_started, trx_mysql_thread_id, trx_query from information_schema.i ...
- MySQL 优化 (三)
参数优化 query_cache_size (1) 简介: 查询缓存简称QC,使用查询缓冲,mysql将查询结果存放在缓冲区中,今后对于同样的select语句(区分大小写),将直接从缓冲区中读取结果. ...