程序员想法

sed命令详解

2019-12-26  本文已影响0人  ElephantKing

sed命令基本概念

sed命令每次只能处理一行数据,数据的来源可以是:键盘输入、重定向、字符串、文件。每次从元数据读取一行放入缓冲区,依次执行sed命令,直到所有命令完成,再处理下一行。循环往复,直到所有数据行处理完成。
sed命令常见的执行方式有两种,如下:

  1. shell命令中直接使用
sed [option] 'command' input_file
  1. 把sed命令放在文件里,使用时用-f选项指定。
sed [option] -f sed_script_file input_file

sed命令选项

sed命令的选项数量不多,使用起来也不复杂,主要一下几个:

sed文本定位方式

由于sed命令是基于行操作的命令,那么sed是如何定位某一行呢?主要有如下几种方式。

  1. 定位某一行
# 打印input.txt的第4行,配合-n选项,其他的行不会被打印
sed -n '4p' input.txt
sed -n '$p' input.txt
  1. 定位某些行
# 包含abc的行,查找字符串的语法必须是/xxx/前后两个斜杠都需要
sed -n '/abc/p' input.txt
# hello开头的行
sed -n '/^hello/p' input.txt
# 包含至少5个连续字母a的行,下面两个命令等价,原因参见上面的链接
sed -n '/a\{5,\}/p' input.txt
sed -n -r '/a{5,}/p' input.txt
# 定位奇数行,从第1行开始,步长为2
sed -n '1~2p' input.txt
# 从第10行起,步长为3,即输出10 13 16...行
sed -n '10~3p' input.txt
  1. 定位一个区间的行:区间的两个端点可以是上面定位一行的方式的任意组合,用逗号隔开左右端点。示例如下:
# 1-10行
sed -n '1,10p' input.txt
# 5到最后一行
sed -n '5,$p' input.txt
# 1到下一个(从下一行起,没有则到最后一行)包含abc的行
sed -n '1,/abc/p' input.txt
# 第一个包含abc的行到从此行开始下一个找到def的行,
# 如果abc找不到则没有任何输出,def找不到则找到最后一行
sed -n '/abc/,/def/p' input.txt

行区间的定位还有另外一种方式,我把他叫做紧随其后行

# 找到abc及其后3行,这里3的意思是再来3行
# 左端点可以是上面定位一行的任意方式
sed -n '/abc/,+3p' input.txt
  1. 反向选择上面的行
    在上述所有的行定位的方式的基础上,在其后面紧随一个!,表示反向选择行,示例如下:
# 除了第1行都输出
sed -n '1!p' input.txt
# 偶数行
sed -n '1~2!p' input.txt
# 不包含abc的行
sed -n '/abc/!p' input.txt

sed行操作示例

在上面的行定位中,我们只用了行处理的p操作。还有其他很多操作,如下:

p:打印本行
=:打印行号
a\:在定位行后插入文本,可以插入多行,需要用\分隔
i\:在定位行前插入文本
d:删除定位行
c\:用新文本替换定位行
r:从另一个文本中读
w:把定位行写入到一个文件
y:把定位行的字符进行替换
{}:在定位行执行一组命令
s:使用替换模式

还有复杂的和缓冲区相关的后面单独讲

以上为常用处理操作,看示例吧

# 打印包含abc的行
sed -n '/abc/p' input.txt
# 打印最后一行
sed -n '$p' input.txt
# 打印奇数行行号
sed -n '1~2=' input.txt
# 包含abc的行号
sed -n '/abc/=' input.txt
# 在20行后插入hello
sed '20a\hello' input.txt
# 1 4 7..行后插入what the fuck
sed '1~3a\what the fuck' input.txt
# 删除带abc的行
sed -n '/abc/d' input.txt
# 删除第一处包含abc的行及其后2两行
sed -n '/abc/,+2d' input.txt
# 把包含error的行,替换为what
sed '/error/\cwhat' input.txt
# 在包含John的行后面,插入文件score.txt的内容,和\a很像
sed '/John/r score.txt' input.txt
# 把定位的行输出到指定的文件中
sed '/some lines/w out.txt' input.txt
# 在定位行执行字符替换操作:把abc->ABC
sed '1~2y/abc/ABC/' input.txt
# 使用{}包括一组命令,按顺序执行,相当于用-e连接,下面命令等价,注意分号
sed '/1~2{y/abc/ABC/;y/ABC/WTF/;}' input.txt
sed -e '1~2y/abc/ABC/' -e '1~2y/ABC/WTF' input.txt
# s替换字符串
# abc->she
sed 's/abc/she/' input.txt
# 用()包围的内容,改为用{}包围,这里是贪心匹配,sed不支持非贪心模式
sed 's/(\(.*\))/{\1}/g' input.txt
# 替换默认只替换本行的第一个匹配,要替换所有请加g选项
sed 's/abc/DEF/g' input.txt
# 利用{}配合n选项进行操作,名字后面一行是成绩,用于修改成绩
sed '/john/{n;s/score=59/score=100/;}' input.txt

若sed命令放在shell脚本里,并且要使用shell中的变量时,请用双引号代替单引号包裹命令。

高级用法,不常用

两种缓冲区:模式缓冲区(pattern buffer)、保持缓冲区(hold buffer)
五个缓冲区操作命令:

  1. 模式缓冲区的内容会被每次读取的行替代
  2. 保持缓冲区的内容不会主动变化,除非你用上面的h H x命令。
# input.txt内容如下3行
# one
# two
# three
sed -n 'H;g;p;' input.txt
# output:
# 空行
# one
# 空行
# one
# two
# 空行
# one
# two
# three

执行H命令时,模式缓冲区已经读入了第一行内容,所以执行H命令后,把第一行内容附加到保持缓冲区后,并且自动换行,再执行命令g把保持缓冲区的内容(一个空行 one)赋值回模式空间,再执行命令p把模式缓冲区的内容打印出来(打印的总是模式缓冲区的内容)。当读取下一行内容时,模式缓冲区又被替换为读取内容(two),保持缓冲区内容不变(一个空行 one),如此往复构成了这个执行结果。
翻来覆去,一顿操作,暂时看不到使用场景,可以先放着吧。

上一篇下一篇

猜你喜欢

热点阅读