oynix

于无声处听惊雷,于无色处见繁花

sed命令

之前只是大概写过几句,很粗糙,这几天用的很频繁,发现它的功能很多,很强大,所以再来细致的说一说。

1. 简介

常用的功能是:删除文件行,替换行内字符串。基本格式是这样的,可处理文件,也可以处理管道流

1
2
3
4
5
# 从文件读取数据
sed [command] [file]

# 接收并处理管道的数据
cat [file] | sed [command]

原理很直观,按行读取数据到缓冲区,按command处理数据,完成后将缓冲区的数据输出,默认输出的屏幕。从这个流程可以看出,默认情况下,sed命令是不会修改原文件的,但可以通过参数,使其修改原文件。

另外多说一句,Linux上的sed是GNU版本,而Mac上的sed是BSD版本,两个命令名字相同,但有些行为有些差别,如果别人都可以的命令在自己的机器上却不生效,听我的,它就是不行,别浪费时间干耗了,赶紧换个方式,曲线也能救国。

2. 关闭输出到屏幕

通过-n参数,可以关掉sed将每次处理完的数据输出到屏幕的行为,建议关掉

1
sed -n [command] [file]

3. 修改原文件

上面说过,sed不修改原文件,而是将修改后的数据默认输出到屏幕,可通过-i参数来修改这种行为。

1
sed -i 'backup' '3d' file.txt

3d是删除第3行的意思,这行命令执行完之后,会在当前路径下生成一个文件,文件名是在原文件名的基础上,再加上-i指定的后缀,即file.txtbackup,这个文件是修改前的原始内容,而file.txt则是修改后的内容,可以把-i理解为备份原文件。

上面是在Mac上的行为,而在Linux上,-i只是表明要修改原文件,没有参数,也没有其他的操作。

4. 删除命令 d

delete,sed是按行处理数据,所以,若删除便是一整行,而不能只删除其中的字符,文件的首行是第1行。删除一般有这么几种情况,删除某一行、删除某几行,删除符合特定条件的行,比如包含某个关键词,分别说一说。

  • 删除文件的第3行
    1
    sed '3d' file.txt
  • 删除最后一行,这里使用$符号,这和正则里相同
    1
    sed '$d' file.txt
  • 删除文件第2到5行
    1
    sed '2,5d' file.txt
  • 删除包含apple的行
    1
    sed '/apple/d' file.txt
  • 从第2行开始删除,首次遇到含有apple的行后,停止
    1
    sed '2,/apple/d' file.txt
  • 首次遇到含有apple的行开始删除,一直到第10行停止,为什么强调首次呢,因为可能会出现多行都含有apple的情况
    1
    sed '/apple/,10d' file.txt
  • 删除空行,这个命令是个正则表达式,表示开头和结尾挨着的行,也就是空行,但是在Mac上不好使
    1
    sed '/^$/d' file
  • 不删除,即反向删除,上面说的都是符合条件则删除,反向删除是符合条件才不被删除,如,包含apple则不删除,否则删除
    1
    sed '/apple/!d' file

5. 替换命令 s

substitute,替换的意思,命令基本格式如下

1
sed 's/[old]/[new]/[scope]'

同样,还是以行为基本操作单位,将其中的old,替换成new,而scope表示要替换的范围,可能值有1,2…或者g,表示替换该行的第几处,1则只替换该行的第一处的old,2同理,而g表示替换该行里所有的old。old是用来过滤目标字符串的,因为其中的支持多种形式语法,花样繁多,也正是此造就了sed强大的功能。

  • 将每行所有apple替换成banana
    1
    sed 's/apple/banana/g' file.txt
  • 将每行所有apple或者Apple替换成banana,中括号代表一个字符,里面是可能的值
    1
    sed 's/[Aa]pple/banana/g' file.txt
  • 将每行所有apple替换成pineapple,在new中,&代表old的值,所以pipe&就代表pipeapple
    1
    sed 's/apple/pipe&/g'
  • 字符占位,.表示1个字符,比如下面这个命令表示,不管pple前面是什么字符,都会连带着一起替换成banana
    1
    sed 's/.pple/banana/g' file.txt
  • 字符数量,?表示0或者1,*表示0或者多个,{n}表示固定为n个,{n,}表示n个或者更多,{n,m}表示数量在n到m之间。下面这个命令表示把两个连续的a,替换成BB
    1
    sed 's/a\{2\}/BB/g' file.txt

6. 子串

在old里面用小括号可以表示子串,子串按照顺序可在new中用\1,\2表示

1
sed 's/\(a\)\(pple\)/\1-\2/g' file

这条命令中,在old中,apple用括号分成了两部分(a)(pple),其中a是第1个子串,pple是第2个子串,在new中\1和\2分别表示两个子串,最终apple就会被替换成a-pple。

1
sed 's/\(.\)\(pple\)/A\2/g' file

而这条命令,则是用一个句点占位符,所以,不管old中pple前面的字符是什么,最后都会被替换成Apple。

7. 打印命令 p

print,这个命令和删除命令的用法基本一致,即,打印某一行、某几行、符合限定条件的行

1
sed '1,4p' file.txt

8. 写文件命令 w

write,后面跟着输出文件,不存在则创建,存在则覆盖,效果等同于复制。下面这条命令,就会把file.txt的内容写入到cp.txt文件中,w后面可以加个空格,也可以不加

1
sed 'w cp.txt' file.txt

9. 执行多个命令

上面的例子中,我们对每一行只执行了一条命令,实际上可以一次执行多个命令,命令之间用分号分隔。比如,下面这行命令就表示先把该行所有apple替换成banana,然后再把这行输出到result.txt文件中

1
sed 's/apple/banana/g;w result.txt' file.txt

或者,也分开写,但同时要用-e参数,

1
sed -e 's/apple/banana/g' -e 'w result.txt' file.txt
------------- (完) -------------
  • 本文作者: oynix
  • 本文链接: https://oynix.com/2022/05/4ead947635ec/
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

欢迎关注我的其它发布渠道