三剑客之sed
介绍
基础介绍
- sed(Stream Editor),流编辑器。对标准输出或文件逐行进行处理
语法格式
- 第一种形式:stdout | sed [option] “pattern command”
- 第二种形式:sed [option] “pattern command” file
处理过程
sed 编辑器逐行处理文件(或输入),并将输出结果发送到屏幕。 sed 的命令就是在 vi和 ed/ex 编辑器中见到的那些。 sed 把当前正在处理的行保存在一个临时缓存区中,这个缓存区称为模式空间或临时缓冲。sed 处理完模式空间中的行后(即在该行上执行 sed 命令后),就把改行发送到屏幕上(除非之前有命令删除这一行或取消打印操作)。 sed 每处理完输入文件的最后一行后, sed 便结束运行。 sed 把每一行都存在临时缓存区中,对这个副本进行编辑,所以不会修改或破坏源文件。
sed选项
选项 | 含义 |
---|---|
-n | 只打印模式匹配行 |
-e | 直接在命令行进行sed编辑,默认选项 |
-f | 编辑动作保存在文件中,指定文件执行 |
-r | 支持扩展正则表达式 |
-i | 直接修改文件内容 |
sed中的pattern详解
pattern用法表
匹配模式 | 含义 |
---|---|
10command | 匹配到第10行 |
10,20command | 匹配从第10行开始,到第20行结束 |
10,+5command | 匹配从第10行开始,到第16行结束 |
/pattern1/command | 匹配到pattern1的行 |
/pattern1/,/pattern2/command | 匹配到pattern1的开始行,到匹配到pattern2的结束行 |
10,/pattern1/command | 匹配从第10行开始,到匹配到pattern1的行结束 |
/pattern1/,10command | 匹配到pattern1的行开始,到第10行匹配结束 |
练习
用法 | 命令 | 说明 |
---|---|---|
LineNumber—直接指定行号 | sed -n “17p” file | 打印file文件的第17行 |
StartLine,EndLine—指定起始行号和结束行号 | sed -n “10,20p” file | 打印file文件的10到20行 |
StartLine,+N—指定起始行号,然后后面N行 | sed -n “10,+5p” file | 打印file文件中从第10行开始,往后面加5行 |
/pattern1/—正则表达式匹配的行 | sed -n “/^root/p” file | 打印file文件中以root开头的行 |
/pattern1/,/pattern2/—从匹配到pattern1的行开始,到匹配到pattern2的行结束 | sed -n “/^ftp/,/^mail/p” file | 打印file文件中第一个匹配到以ftp开头的行开始,到第二个匹配到以mail开头的行结束 |
LineNumber,/pattern1/从指定行号开始匹配,直到匹配到pattern1的行 | sed -n “4,/^hdfs/p” file | 打印file文件中从第4行开始匹配,直到以hdfs开头的行 |
/pattern1/,LineNumber—从pattern1匹配的行开始,直到匹配到指定的行数结束 | sed -n “/root/,10p” file | 打印file文件中匹配root行,直到第10行结束 |
sed中的编辑命令详解
编辑命令对照表
类别 | 编辑命令 | 含义 |
---|---|---|
查询 | p | 打印 |
增加 | a | 行后追加 |
i | 行前追加 | |
r | 外部文件读入,行后追加 | |
w | 匹配行写入外部文件 | |
删除 | d | 删除 |
修改 | s/old/new | 将行内第一个old替换为new |
s/old/new/g | 将行内全部的old替换为new | |
s/old/new/2g | 将行内前2个old替换为new | |
s/old/new/ig | 将行内old全部替换为new,忽略大小写 | |
其他编辑命令 | = | 显示行号 |
什么是反向引用?
&和\1 引用模式匹配到整个串
sed “s/1..e/&r/g” file 在file中搜索以1开头,然后跟两个任意字符,以e结尾的字符串
sed "s/\(1..e\)/\1r/g" file
和上面实现一样的功能,使用\1代表搜寻到的字符串上面两种方式实现了一样的功能,分别使用&和\1引用前面匹配到整个字符串
两者区别在于&只能表示匹配到的完整字符串,只能引用整个字符串;而\1可以使用()对匹配到的字符串
例如:如果我们仅想要替换匹配到的字符串的一部分,name必须使用\1这种方式,不能使用&
查找test.txt文中以1开头,紧接着跟着两个任意字符,再接一个e的字符串。将找到的字符串中开头的
sed "s/1\(..e\)/L\1/g" test.txt
sed中引用变量时注意事项:
- 匹配模式中存在边,则建议使用双引号
- sed中需要引入自定义变量时,如果外面使用单引号,则自定义变量也必须使用单引号
利用sed查询特定内容
查询命令对照表
查询命令 | 含义 |
---|---|
1p | 打印1行内容 |
1,10p | 打印1行到10行的内容 |
1,+5p | 打印1行到6行的内容 |
/pattern1/p | 打印每行中匹配到pattern1的行内容 |
/pattern1/,/pattern2/p | 打印匹配到pattern1的行直到匹配到pattern2的所有内容 |
/pattern1/,10p | 打印匹配到pattern1的行到10行的所有行内容 |
10,/pattern1/p | 打印第10行直到匹配到pattern1的所有行内容 |
练习
打印/etc/passwd中第20行的内容 | sed -n ‘20p’ /etc/passwd |
---|---|
打印/etc/passwd中从第8行开始,到第15行结束的内容 | sed -n ‘8,15p’ /etc/passwd |
打印/etc/passwd中从第8行开始,然后+5行结束的内容 | sed -n ‘8,+5p’ /etc/passwd |
打印/etc/passwd中开头匹配lvjing字符串的内容 | sed -n ‘/^lvjing/p’ /etc/passwd |
打印/etc/passwd中开头为root的行开始,到开头为hdfs的行结束的内容 | sed -n ‘/^root/,/^hdfs/p’ /etc/passwd |
打印/etc/passwd中第8行开始,到含有/sbin/nologin的内容的行结束内容 | sed -n ‘8,//sbin/nologin/p’ /etc/passwd |
打印/etc/passwd中第一个包含/bin/bash内容的行开始,到第5行结束的内容 | sed -n ‘//bin/bash/,5p’ /etc/passwd |
脚本练习
需求描述:处理一个类似MySQL配置文件my.cnf的文本,示例如下:
1 | [client] |
编写脚本实现以下功能:输出文件有几个段,并且针对每个段可以统计配置参数总个数(需要去除空行和注释)
预期输出结果:
1:client xx
2:mysqld xx
3:mysqldump xx
4:mysql xx
5:isamchk xx
6:myisamchk xx
7:mysqlhotcopy xx
function get_all_segment
function count_items_in_segment #根据段名查找下面的内容,段名间的匹配
获取段的个数:
1 | [root@iZ2ze0gzw63rkie6uwjs74Z lvjing]# grep -E "^\[" my.cnf |
脚本实现:
1 | ! /bin/bash |
执行结果:
1 | [root@iZ2ze0gzw63rkie6uwjs74Z lvjing]# sh example.sh |
利用sed删除特定内容
删除命令对照表
查询命令 | 含义 |
---|---|
1d | 删除第1行内容 |
1,10d | 删除1行到10行内容 |
1,+5d | 删除1行到6行内容 |
/pattern1/d | 删除每行中匹配到pattern1的行内容 |
/pattern1/,/pattern2/d | 删除匹配到pattern1的行直到匹配到pattern2的所有行内容 |
/pattern1/,10d | 删除匹配到pattern1的行到10行的所有行内容 |
10,/pattern1/d | 删除第10行直到匹配到pattern1的所有行内容 |
练习
删除/etc/passwd中的第15行 | sed -i ‘15d’ passwd |
---|---|
删除/etc/passwd中的第8行到第14行的所有内容 | sed -i ‘8,14d’ passwd |
删除/etc/passwd中不能登录的用户(筛选条件/sbin/nologin) | sed -i ‘/\sbin/nologin/d’ passwd |
删除/etc/passwd中以mail开头的行,到以yarn开头的行的所有内容 | sed -i ‘/^mail/,/^yarn/d’ passwd |
删除/etc/passwd中第一个不能登录的用户,到第13行的所有内容 | sed -i ‘/\sbin/nologin/,13d’ passwd 这种方式有缺陷,13行后还会继续匹配不能登录的用户进行删除 |
删除/etc/passwd中第5行到以ftp开头的所有行的内容 | sed -i ‘5,/^ftp/d’ passwd |
删除/etc/passwd中已yarn开头到最后行的所有内容 | Sed -i ‘/^yarn/,$’ passwd |
删除/etc/passwd中不能登录的所有用户 | sed -i ‘/\sbin/nologin/d’ passwd |
注意:
-i
直接修改文件内容- /etc/passwd是重要文件,需要拷贝一个文件进行操作
$
表示最后一行
脚本练习
删除配置文件中的所有注释行和空行
1
sed -i '/^#/d;/^$/d' my.cnf
注意:上面的命令只会将
#
顶头的行删除,剩下的行有空格带有#
注释的行则不会删除1
2my.cnf# 删除带有空格的#行
sed -i '/[:blank:]*#/' my.cnf[:blank:]* 表示空格字符
在配置文件中所有不以#开头的行前面添加*符号,注意:以#开头的行不添加
1
sed -i 's/^[^#]/\*&/g' my.cnf
^[^#]
非警号开头的行
利用sed修改文件内容
修改命令对照表
编辑命令 | 含义 |
---|---|
1s/old/new/ | 替换第1行内容old为new,如果不加数字,则是每一行 |
1,10s/old/new/ | 替换1行到10行的内容old为new |
1,+5s/old/new/ | 替换1行到6行的内容old为new |
/pattern1/s/old/new/ | 替换匹配到pattern1的行内容old为new |
/pattern1/,/pattern2/s/old/new | 替换匹配到pattern1的行直到匹配到pattern2的所有行内容old为new |
/pattern1/,10s/old/new/ | 替换匹配到pattern1的行到10行的所有行内容old为new |
10,/pattern1/s/old/new/ | 替换第10行直到匹配到pattern1的所有行内容old为new |
练习
修改/etc/passwd中第一行中第1个root为ROOT | sed -i ‘1s/root/ROOT/‘ passwd |
---|---|
修改/etc/passwd中第5行到第10行中所有的/sbin/nologin为/bin/bash | sed -i ‘5,10s//sbin/nologin//bin/bash/g’ passwd |
修改/etc/passwd中匹配到/sbin/nologin,将匹配到行中的login中改为大写的LOGIN | sed -i ‘//sbin/nologin/s/login/LOGIN/g’ passwd |
修改/etc/passwd中从匹配到以root开头的行,到匹配到行中包含mail的所有行。修改内容为将这些所有匹配到的行中的bin改为HADOOP | sed -i ‘/^root/,/mail/s/bin/HADOOP/g’ passwd |
修改/etc/passwd中从匹配以root开头的行,到第15行中的所有行,修改内容为将这些行中的nologin修改为SPARK | sed -i ‘/^root/,15s/nologin/SPARK/g’ passwd |
修改/etc/passwd中从第15行开始,到匹配到以yarn开头的所有行,修改内容为将这些行中的bin修改为BIN | sed -i ‘15,/^yarn/s/bin/BIN/g’ passwd |
利用sed追加文件内容
追加用法总结
- a 在匹配行后面追加
- i 在匹配行前面追加
- r 将文件内容追加到匹配行后面
- w 将匹配行写入指定文件
追加用法示例详解
a append
passwd文件第10行后面追加”Add Line Behind”
1
sed -i '10a Add Line Behind' passwd
passwd文件第10行到第20行,每一行后面都追加”Test Line Behind”
1
sed -i '10,20s Test Line Behind' passwd
passwd文件匹配到/bin/bash的行后面追加”Insert Line For /bin/bash Behind”
1
sed -i '/\/bin\/bash/a Insert Line For /bin/bash Behind' passwd
- i
passwd文件匹配到以yarn开头的行,在匹配行前面追加”Add Line Before”
1
sed -i '/^yarn/i Add Line Before' passwd
passwd文件每一行前面追加”Insert Line Before Every Line”
1
sed -i 'i Insert Line Before Every Line' passwd
- r
将/etc/fstab文件的内容追加到passwd文件的第20行后
1
sed -i '20r /etc/fstab' passwd
将/etc/inittab文件的内容追加到passwd文件匹配/bin/bash行的后面
1
sed -i '/\/bin\/bash/r /etc/inittab' passwd
将/etc/vconsole.conf文件内容追加到passwd文件特定行后面,匹配已ftp开头的行,到第18行的所有行
1
sed -i '/^ftp/,18r /etc/vconsole.conf' passwd
w
将passwd文件匹配到/bin/bash的行追加到/tmp/sed.txt文件中
1
sed -i '/\/bin\/bash/w /tmp/sed.txt' passwd
将passwd文件从第10行开始,到匹配到hdfs开头的所有行内容追加到/tmp/sed-1.text
1
sed -i '10,/^hdfs/w /tmp/sed-1.text' passwd