之前只是大概写过几句,很粗糙,这几天用的很频繁,发现它的功能很多,很强大,所以再来细致的说一说。
1. 简介
常用的功能是:删除文件行,替换行内字符串。基本格式是这样的,可处理文件,也可以处理管道流
1 | 从文件读取数据 |
原理很直观,按行读取数据到缓冲区,按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前面是什么字符,都会连带着一起替换成banana1
sed 's/.pple/banana/g' file.txt
- 字符数量,
?
表示0或者1,*
表示0或者多个,{n}
表示固定为n个,{n,}
表示n个或者更多,{n,m}
表示数量在n到m之间。下面这个命令表示把两个连续的a,替换成BB1
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 |