文本处理sed命令
如果觉得对你有帮助,能否点个赞或关个注,以示鼓励笔者呢?!博客目录 | 先点这里
- 前提概念
- 什么是sed命令
- sed命令的语法格式
- 使用注意事项
- sed命令的三个概念
- option 选项模式
- pattern 模式匹配
- command 命令操作
- sed命令实践
前提概念
什么是sed命令
- sed(Stream Editor),流编辑器。对标准输出或文件逐行进行处理
- sed的工作模式,说白了就是根据pattern去逐行匹配行,如果行匹配,我们就对该行执行command命令,处理它
语法格式
sed的使用格式通常有两种
- 第一种
stdout | sed [option] "pattern command"
- 第二种
sed [option] "pattern command" file
说白了,就三个概念要重点记住
- option选项
- pattern匹配行
- command命令
使用注意事项
- 填写pattern时,要注意转义一些特殊字符,比如一些路径/符号,需要通过\去转义
- 匹配模式pattern如果存在变量,既我们pattern中存在使用$variable的方式获取变量,建议使用双引号。比如 sed “s/$old/$new/g” file , 如果是单引号,pattern会把$old取变量的意思当做是"$old"字符串来处理
- 如果匹配模式pattern如果存在变量,你又想使用单引号来括住pattern, 那你的取变量也要被单引号括住吗,比如 sed ‘s/’$old’/’$new’/g’ file
sed命令的三个概念
sed的选项(option)
-n
开启流中只有匹配行。 默认我们sed流存储的就是文件原始数据。如果我们的是命令p,就相当于在流中再次输入了匹配行,比如全局打印输出,就相当于把sed流的原始文本拷贝了一份又存储在流中,此时流中就有两份数据,此时如果我们只想让流保留匹配行,可以使用-n;针对增删改的command,不要-n的使用,因为增删改不像p命令是打印一份数据到流中,而是直接针对流中的原始数据进行增删改,如果对增删改操作开启-n ,就会导致流中只有匹配行的数据增删改的数据。尤其是搭配-i时,容易导致原文本数据丢失-e
直接在命令行进行sed编辑,默认选项。 什么是sed编辑呢?'pattern command’就是一个sed编辑,通常我们都在一个sed命令中写一个sed编辑去匹配行处理行,比如sed '/python/ p' file
, 代表输出含python字符串的行。如果我们不仅想匹配带有python字符串的行,还想带java的行也输出怎么办?-e
就派上用场了。sed -e '/python/ p' -e /java p/ file
实现两个模式匹配,说白了当你只有一个sed编辑时,-e是隐式自带的。-f
编辑动作保存在文件中,指定文件执行。 说白了,-f 就是 -file, 指定文件的路径。就是说,如果我们的sed命令比较长,我们可以把它放到一个文件中,通过-f选项来指定文件执行命令。比如sed -f sedfile file
, 载入sedfile的sed命令去处理file文件的行-r
支持扩展正则表达式。 说白了,-r就是-regex。因为sed的pattern模式不支持正则表达式,所以当我们要执行含java或python字符串的行时,我们原生sed的pattern可以要用到-e得多模式匹配方法sed -e '/python/ p' -e /java p/ file
。这时我们再想,如果我们可以使用正则表达式就好了,一个|
符号就解决了。所以sed提供了-r的支持正则表达式的选项。sed -r '/python|java/ p' file
-i
直接修改文件内容。 就是说sed的command对行进行处理,虽然流中是处理后的结果,但是实际文件是不会被处理的。学过Java的Stream也知道,流出来是不会对原数据产生影响的,处理你执行了终结命令覆盖数据。-i
就是sed命令的终结命令,将流处理后的结果覆盖到原数据中,会对原数据产生影响
匹配模式pattern
pattern就类似于正则表达式的模式匹配,在sed的格式规范中,sed的pattern是有由'/pattern/'
两个/
符号括起来的 。用于匹配目的行数据,让匹配行得以执行command命令
(一) 隔开pattern和command命令
- pattern和command之间可以用空格和
分号;
隔开彼此,甚至不用隔开也行 - command和command之间通过空格和
分号;
隔开彼此,也可以不隔开
sed '/python/p' file
sed '/python/ p' file
sed 'python/;p' file
(二) pattern用法表
pattern支持单pattern匹配,也支持范围匹配,甚至全局匹配(没pattern就是处理所有行)。范围匹配呢,支持pattern之间,也支持数字之间,也支持pattern和数字混合式。注意在范围匹配中,如果文件中没有行数据匹配后面边界的pattern,那么他会匹配到文件末尾,比如从10行到文件末尾的所有行都执行command;同时如果范围匹配中,前面是模式匹配,后面是行数匹配,行数之前没有成功模式匹配,行数就会失效,称为普通的模式匹配
10command
匹配到第10行10,20command
匹配从第10行开始,到第20行结束10,+5command
匹配从第10行开始,到第16行结束/pattern/command
使用pattern匹配行/pattern1/,/pattern2/command
从匹配pattern1的行到匹配pattern2的行都执行command , 匹配一个范围10,/pattern/command
从第10行开始,到pattern行,都执行command命令,匹配一个范围。/pattern/,10command
从pattern匹配行到第10行都执行command命令,匹配一个范围。
sed命令支持类似正则的匹配规则
/name/command
匹配行数据中带有name字符串的行数据,执行command命令/^name/command
匹配行数据以name字符串开头的行数据,执行command命令
command命令
(一) 命令操作类型
command命令就是sed中的编辑命令, 主要就是对匹配行进行增
,删
,改
,查
的工作
查询
p
打印匹配行
增加
a
在匹配行的行后追加数据,准确的说追加的数据是原数据的下一行i
在匹配行的行前追加数据,准确的说是追加的数据是原数据的上一行r
在匹配行的行后,追加从外部文件读入的数据w
将匹配行数据写入外部文件中
删除
d
删除匹配行数据
修改
s/old/new
将匹配行的第一个old字符串用new字符串替换s/old/new/g
将匹配行的所有old字符串用new字符串替换s/old/new/2
将匹配行前两个old替换为news/old/new/2g
从匹配行的第二个old开始,将之后的所有old替换成news/old/new/ig
将匹配行所有old字符串替换为new字符串,且忽略大小写
其他编辑命令
=
输出匹配行数据的行号
(二) 反向引用延伸,变量
-
&和\1
反向引用,是模式匹配串的引用,比如sed 's/hello/& world/g' file
,就是将hello替换成hello world,&
和\1
可以作为old的对象引用 。
\1
比&
要更加灵活,\1
只引用括号内部的字符串,比如sed 's/\(he\)llo/\1 world/g' file
,将所有hello替换成he world, 记住()是特殊字符,需要转义 -
匹配模式pattern如果存在变量,既我们pattern中存在使用$variable的方式获取变量,建议使用双引号。比如 sed “s/$old/$new/g” file , 如果是单引号,pattern会把$old取变量的意思当做是"$old"字符串来处理
-
如果匹配模式pattern如果存在变量,你又想使用单引号来括住pattern, 那你的取变量也要被单引号括住吗,比如 sed ‘s/’$old’/’$new’/g’ file
sed命令实践
打印所有行
- hello文件
I love python
I love PYTHON
hadoop is bigdata frame
- sed命令 :
sed 'p' hello
# output:
I love python
I love python
I love PYTHON
I love PYTHON
hadoop is bigdata frame
hadoop is bigdata frame
'p'
就是一个command, 代表打印的意思,因为我们没有写pattern, 所有该命令的意思就是打印所有的行。那么为什么会打印两遍?这就是sed的工作机制,首先第一遍是原行数据,第二遍是'p'
命令对原行执行命令的结果。我们可以通过option-n
去设置模式,只输出模式匹配行,不输出原行数据即可- 说白了sed的行处理机制就是,默认情况下,先输出原行数据,再输出处理后的数据
打印符合pattern的行数据
- hello文件
I love python
I love PYTHON
hadoop is bigdata frame
- sed命令 :
sed -n '/python/ p' hello
, 打印所有带有python字符串的行数据
# output:
i love python
- sed命令:
sed -n '/p.*/ p hello'
,打印所有带有p字符的行数据,p后面可以跟任何字符
# output
I love python
hadoop is bigdata frame
输出某个文件中指定行数范围的行数据
- hello文件
1
2
3
4
5
6
7
- sed命令:
sed -n '5,7p' hello
输出5到7行的数据
# output:
5
6
7
- sed命令:
sed -n '1,+3p' hello
输出1到1+3=4行的数据
# output
1
2
3
4
- sed命令:
sed -n '1,/6/p' hello
输出第1行到匹配带有6字符的行数据(如果多个地方有6,匹配到顺位第一个),重点!!如果没有任何数据带有6,那么它会匹配到文件末尾。
# output
1
2
3
4
对匹配行进行增加命令操作
- hello文件
I love python
I love PYTHON
hadoop is bigdata frame
- sed命令:
sed -i '2a hello world' hello && cat -n hello
, 在第2行后追加helloworld字符串并更新入原文件,并查看hello文件, 显示行号
1 I love python
2 I love PYTHON
3 hello world
4 hadoop is bigdata frame
- sed命令:
sed -i '2i hello world' hello && cat -n hello
, 在第2行前追加helloworld字符串并更新入原文件,并查看hello文件, 显示行号
1 I love python
2 hello world
3 I love PYTHON
4 hadoop is bigdata frame
- sed命令:
sed '2i r /etc/intput' hello
, 在第2行后追加/etc/intput文件中的文本内容 - sed命令:
sed '/python/i w /etc/output' hello
将所有带有python的行数据都写入外部文件/etc/output中
对匹配行进行删除命令操作
- hello文件
I love python
I love PYTHON
hadoop is bigdata frame
- sed命令:
sed -n '3d;p' hello
对第三行进行删除,然后输出删除后的结果
I love python
I love PYTHON
- sed命令:
sed -n -r '/python|PYTHON/ d;p' hello
删除带有python或PYTHON字符串的行,并输出剩余结果
hadoop is bigdata frame
对匹配行进行修改命令操作,替换
- hello文件
I love python
I love PYTHON
hadoop is bigdata frame
- sed命令:
sed -n 's/love/hate/g p' hello
, 将行数据带有love字符串全部替换成hate字符串
I hate python
I hate PYTHON
显示输出匹配行的行号
- hello文件
I love python
I love PYTHON
hadoop is bigdata frame
- sed命令:
sed -n -r '/python|PYTHON/=' hello
,显示带有python或PYTHON字符串的行数据的行号
1
2
参考资料
- 《鸟哥的Linux私房菜》
- 跟着360架构师 学习Shell脚本编程 -@作者:酷田
- 如果觉得对你有帮助,能否点个赞或关个注,以示鼓励笔者呢?!