linux三剑客之sed详解

发布时间 2023-03-26 16:42:39作者: 小刘的早餐店

1.什么是sed

sed是stream editor的简写,也就是流编辑器的意思,可不要看做seed(种子)哦, Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等

2.新手入门

在学习这个命令之前,我们先来看一个sed的最基本的实例,然后一步步的学习更深层次的用法

_> cat test.txt
This is my cat
  my cat's name is betty
This is my dog
  my dog's name is frank
This is my fish
  my fish's name is george
This is my goat
  my goat's name is adam

我们想把test.txt中的This替换为That,可以使用下面的命令

_>sed 's/This/That/' test.txt
That is my cat
  my cat's name is betty
That is my dog
  my dog's name is frank
That is my fish
  my fish's name is george
That is my goat
  my goat's name is adam

通过sed已经把文本中的This替换成了That,是不是很简单,这样就不用在文本编辑器中ctrl+r替换操作了,需要注意的是此时test.txt的文本并没有发生变化,只是做了输出在屏幕上,那怎么才能更改test.txt文件?如何控制在文件固定位置进行操作?怎么和正则表达式结合?是否还有更加高级的用法?带着这些问题,我们来一步步解开sed的神秘面纱。

3.用法详解

sed的语法:
sed options... [script] [input_file...]

options 解释
-n 取消默认输出
-e 执行多条命令
-f 从脚本文件中读取命令
-i 直接编辑原文件
-r 在脚本中使用扩展表达式
_> sed -n 's/This/That/' test.txt  //默认替换完毕之后是输出到屏幕上,加上-n之后不会输出
_> sed -e 's/This/That/' -e 's/That/This' test.txt  //第一个把This替换为That,第二个命令又把第一个替换后的That替换回来,可以想象成工厂的流水线操作
_> sed  's/This/That/;s/That/This/' test.txt //上面多条命令的简写,中间使用分号‘;’隔离
_> echo s/This/That/ > my.sed //把指令先写到my.sed文件中
_> sed -f my.sed test.txt //从my.sed读取指令,多用于指令的保存
_> sed -i 's/This/That/' test.txt // 直接保存在test.txt中,不会输出到屏幕
# 当命令中出现+、?、|、[]、()等元字符的扩展时要使用-r
_>sed -r 's/is?/!!' test.txt

4.进阶使用

4.1标志位

s/old/new/标志位

标志位 解释
g 每次出现都进行替换
数字 第几次出现在进行替换
p 打印模式空间的内容,模式空间会在原理中说明
w 将模式空间的内容写入到文件
d 删除,模式空间中的值清空,后面的指令都不会执行
a append
i insert
c 改写该行
r 读取文件
q 退出
_> sed  's/This/That/g' test.txt //每行默认只会执行一次替换,使用g作为标志位可以整行符合的都替换
_> sed  's/This/That/3' test.txt //只会替换每行第三次的文本
_> sed  's/This/That/3g' test.txt //只会替换每行第三次或之后的文本
_> sed 's/betty/!!!!!/p' test.txt//betty下面一行也是模式空间的内容
_> sed -n 's/betty/!!!!!/p' test.txt//betty p和-n搭配只输出替换成功的行
_> sed -n 's/betty/!!!!!/w /data/a.txt' test.txt//替换成功的行输出到/data/a.txt中
_> sed '/betty/d' test.txt //删除包含betty的行
_> sed  '/betty/d;s/is/is1/g' test.txt //删除betty的行,没有betty的行会把is替换为is1
_> sed '/betty/a 11111/' test.txt //在匹配到betty的行后追加一行11111
_> sed '/betty/i 11111/' test.txt //在匹配到betty的行前加一行11111
_> sed '/betty/c 11111/' test.txt //把匹配到的betty的行更改为11111
_> sed '/betty/r a.txt/'  test.txt //把匹配到的betty的行更改为a.txt的内容
_> sed '3q' test.txt //输出前三行的数据

4.2 分组功能

命令中可以使用括号进行分组,分组后可进行回调

_>sed 's/(That)/\1:\1/' test.txt //把That看做一个分组,使用\1(代表第一个分组):\1的格式替换

4.3 寻址

寻址也就是选择想要的行进行处理,有三种方式

  • /regx/s/old/new/g
  • 行号s/old/new/g ,如果是最后一行可以用$代替
  • 混合前面的两种
_> sed '/cat/s/is/is1/g' test.txt //匹配出包含cat的行,is替换为is1
_> sed '1s/is/is1/g' test.txt //第一行的才进行替换
_> sed '3,$s/is/is1/g' test.txt //第三行到最后一行的才替换
-> sed '/frank/,$s/is/is1/g' test.txt //混合使用,从包含frank到最后一行的进行替换
-> sed '/frank/,${s/is/is1/;s/frank/frank1} test.txt //一个正则匹配执行两个替换命令

4.4 多行模式空间

  • N 把下一行的内容纳入当成缓冲区做匹配
_>sed 'N;s/\n/,/' test.txt //读取下一行文本,把换行替换为,
  • 保持空间和模式空间结合
    image
    保持空间的四个指令:
    g: 将hold space中的内容拷贝到pattern space中,原来pattern space里的内容清除
    G: 将hold space中的内容append到pattern space\n后
    h: 将pattern space中的内容拷贝到hold space中,原来的hold space里的内容被清除
    H: 将pattern space中的内容append到hold space\n后
    x: 交换pattern space和hold space的内容
_>sed -n '1!G;h;$p' test.txt //翻转行 
#解析上条命令,读取第一行时,G把保持空间的数据拷贝到模式空间中,保持空间模式是\n,h后模式空间是1\n,保持空间1\n
读取到第二行数据时,G操作后模式空间是2\n1\n,h操作后保持空间也为2\n1\n
读取到第三行数据时,G操作后模式空间是3\2\n1\n,h操作后保持空间也为3\2\n1\n
...
读取到最后一行时m时,G操作后模式空间是m\nm-1...3\2\n1\n,h操作后保持空间也为m\nm-1...3\2\n1\n
模式空间第多了一个最后\n,所以在读取第一行时不拷贝,也就是1!G,然后只输出最后一次$p

sed原理

依次读取一行数据到模式空间(patter space),由模式空间处理数据

注意事项

  • 如果想替换命令中包含‘/’的指令,需要自定义一个分割符,例如
_>sed 's/s///' test.txt //把文本中包含s的替换为/,这样写会报错
_>sed 's|s|/|' test.txt //正确写法可以用|作为分割,当然也可以使用其他符号
  • 包含转义字符,需要使用双引号
_>sed 's/my/liu's/' test.txt //错误
_>sed "s/my/liu's/" test.txt //正确

参考数据

https://coolshell.cn/articles/9104.html#用s命令替换
https://time.geekbang.org/course/intro/100029601