sed常用用法的小结

本文详细介绍了sed命令的常用选项、动作以及实例,包括如何增加行、删除行、打印行、替换文本等内容。强调了在确保命令无误后使用选项直接修改文本的重要性,并给出了修改软连接文件和批量替换文本的操作方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

sed(stream editor)命令是一个面向字符流的非交互式编辑器,是按行来处理文本内容的;它还能配合管线来使用,非常高效

我之所以想学会使用这个命令,是因为:当同一个长文本每次执行只需要修改一个小地方时,使用sed能直接对文本操刀,避免使用复杂的python文本生成来覆盖原文本,配合bash脚本使用简直美滋滋

需要注意的另一个点是:可以先使用sed确保命令本身没问题,再使用-i选项直接修改文本(不使用-i选项,执行sed命令后原文本文件不会被修改)

sed [选项] {动作或脚本命令, 如果没有其他脚本的话} 文本文件名
1. 常用选项
  • -n: 安静模式,只打印被修改了的行
  • -e <script>: 使用选项中指定的script来处理输入的文本文件
  • -f <script文件>: 使用选项中指定的script文件来处理输入的文本文件
  • -r: 在动作中使用扩展的正则表达式(默认是基础正则表达式,比如使用限定符会无效等)
  • -i: 直接对文本文件操刀,而不是打印结果到终端
  • --follow-symlinks: 保持软连接文件的连接,硬连接没招儿
  • --version: 打印版本信息
2. 常用动作
  • p: 列出选中的行
  • a: 在指定行后面追加文本
  • i: 在指定行前面插入文本
  • d: 删除指定的行
  • c: 用新文本替换掉选中的行
  • s/正则表达式或指定文本/新文本/: 用新文本替换匹配到的内容,最后加g表示全部替换,否则只替换每一行的第一个匹配内容。而实际上/在这里只是分隔符,s后面紧接着的就是分隔符,可以用别的符号代替,例如#@等(亲测)。

一般脚本命令前面会加指定行区间,比如加2表示只对第2行进行操作,2,$表示对第2行至最后一行进行操作等

3. 实例

原文本内容:

ubuntu@ubuntu:~$ cat test
hello linux!
i have 10 apples.
i have no idea for this file.
233333
增加行
ubuntu@ubuntu:~$ sed '3a\add newline after 3rd line.' test
hello linux!
i have 10 apples.
i have no idea for this file.
add newline after 3rd line.
233333

ubuntu@ubuntu:~$ sed '3i\add newline before 3rd line.' test 
hello linux!
i have 10 apples.
add newline before 3rd line.
i have no idea for this file.
233333

ubuntu@ubuntu:~$ sed '1,2a\add newline after 1st and 2nd line.' test 
hello linux!
add newline after 1st and 2nd line.
i have 10 apples.
add newline after 1st and 2nd line.
i have no idea for this file.
233333
删除行
ubuntu@ubuntu:~$ sed '2d' test
hello linux!
i have no idea for this file.
233333

ubuntu@ubuntu:~$ sed '2,$d' test
hello linux!

ubuntu@ubuntu:~$ sed -r '/[0-9]+/d' test
hello linux!
i have no idea for this file.
打印行
ubuntu@ubuntu:~$ sed -r -n '/[0-9]+/p' test
i have 10 apples.
233333
替换整行
ubuntu@ubuntu:~$ sed '/^i/c replace' test 
hello linux!
replace
replace
233333

ubuntu@ubuntu:~$ sed '1c replace heihei' test
replace heihei
i have 10 apples.
i have no idea for this file.
233333
替换行内的部分内容(含大小写转换)
ubuntu@ubuntu:~$ sed -r '2s/[0-9]+/20/g' test
hello linux!
i have 20 apples.
i have no idea for this file.
233333

ubuntu@ubuntu:~$ sed -r 's/^[a-z]/\u&/g' test
Hello linux!
I have 10 apples.
I have no idea for this file.
233333

ubuntu@ubuntu:~$ sed -r 's/\b[a-z]/\u&/' test
Hello linux!
I have 10 apples.
I have no idea for this file.
233333

ubuntu@ubuntu:~$ sed -r 's/\b[a-z]/\u&/g' test 
Hello Linux!
I Have 10 Apples.
I Have No Idea For This File.
233333

ubuntu@ubuntu:~$ echo 'abcbc' | sed 's@b@B@'
aBcbc

【注】说一下\u的意思:\u是转换后面的内容第一个字母为大写,\U是全部为大写直到遇到\E为止。同理,\l\L的作用类似,只是把大写变为小写。

ubuntu@ubuntu:~$ sed -r 's/[a-z]/\U&/g' test
HELLO LINUX!
I HAVE 10 APPLES.
I HAVE NO IDEA FOR THIS FILE.
233333

ubuntu@ubuntu:~$ sed -r 's/[a-z]/\U&/' test
Hello linux!
I have 10 apples.
I have no idea for this file.
233333
连续命令

sed -e 命令脚本1 -e 命令脚本2 -e 命令脚本3 文本文件名

ubuntu@ubuntu:~$ sed -e '1a\add oneline' -e '$d' test
Hello linux!
add oneline
I have 10 apples.
I have no idea for this file.

【注】上面的实例都是没有直接操刀原文本文件的,也就是说,上面实例的命令执行完毕之后原文本文件并没有被修改。实际应用中应该明白到随意直接修改原文本是很危险的,所以应该在确保命令没有问题之后,再在信任的sed命令中加上-i选项,效果如下所示:

ubuntu@ubuntu:~$ sed -ir 's/[a-z]/\U&/' test
ubuntu@ubuntu:~$ cat test
Hello linux!
I have 10 apples.
I have no idea for this file.
233333
修改软连接文件

加上--follow-symlinks这个选项即可。具体解释如下:

我们知道,硬连接的两个文件的inode的值是一样的(文件类型是-),而软连接的两个文件的inode是不一样的(连接文件的类型是l)。但是在使用sed -i命令修改了连接文件内容后,被修改的软连接文件就会变成普通文件(-),硬连接文件的inode值就会被改变,像这样:

  • 软连接文件
ubuntu@ubuntu:~$ ll -i testa testb
7866189 -rw-rw-r-- 1 ubuntu ubuntu 12  1月 12 20:29 testa
7864805 lrwxrwxrwx 1 ubuntu ubuntu  9  1月 12 20:39 testb -> testa
ubuntu@ubuntu:~$ sed -i '2c replace' testb 
ubuntu@ubuntu:~$ ll -i testa testb
7866189 -rw-rw-r-- 1 ubuntu ubuntu 12  1月 12 20:29 testa
7866188 -rw-rw-r-- 1 ubuntu ubuntu 13  1月 12 20:41 testb
  • 硬连接文件
ubuntu@ubuntu:~$ ll -i testa testb 
7866189 -rw-rw-r-- 2 ubuntu ubuntu 12  1月 12 20:29 testa
7866189 -rw-rw-r-- 2 ubuntu ubuntu 12  1月 12 20:29 testb
ubuntu@ubuntu:~$ sed -i '2c replace' testb.txt 
ubuntu@ubuntu:~$ ll -i test test 
7866189 -rw-rw-r-- 1 ubuntu ubuntu 12  1月 12 20:29 testa
7864805 -rw-rw-r-- 1 ubuntu ubuntu 13  1月 12 20:38 testb

实际上,只要使用sed -i命令修改了文件内容,那么文件的inode值一定会变,像这样:

  • 普通文件
ubuntu@ubuntu:~$ ll -i testc
7866191 -rw-rw-r-- 1 ubuntu ubuntu 10  1月 12 20:31 testc
ubuntu@ubuntu:~$ sed -i '2c replace' testc 
ubuntu@ubuntu:~$ ll -i testc
7864805 -rw-rw-r-- 1 ubuntu ubuntu 13  1月 12 20:42 testc

所以,修改了硬连接文件的文件内容又想保持连接,没招儿(有人说-c选项可以,但我试了,不行)。

而要使得修改后的软连接文件还能保持连接,就需要加上--follow-symlinks这个选项,不过这个时候就是原文件的inode值变了(原文件被修改了),像这样:

ubuntu@ubuntu:~$ ll -i testa testb
7866189 -rw-rw-r-- 1 ubuntu ubuntu 12  1月 12 20:29 testa
7866188 lrwxrwxrwx 1 ubuntu ubuntu  9  1月 12 20:44 testb -> testa
ubuntu@ubuntu:~$ sed -i --follow-symlinks '2c replace' testb 
ubuntu@ubuntu:~$ ll -i testa testb
7866190 -rw-rw-r-- 1 ubuntu ubuntu 13  1月 12 20:45 testa
7866188 lrwxrwxrwx 1 ubuntu ubuntu  9  1月 12 20:44 testb -> testa

感谢 @Qingqing1992 的留言!

批量替换
sed -i 's/旧字符串/新字符串/g' `grep 旧字符串 -rl 路径`
sed -i 's/旧字符串/新字符串/g' *
  • 在指定路径下递归匹配所有含有旧字符串的文件,执行sed,例如:

    sed -i 's/218.192.160.64/0.0.0.0/g' `grep 218.192.160.64 -rl ./` 
    
  • 对当前目录下所有文件执行sed,当前目录不允许有不是文件的文件(例如目录)

    sed -i 's/218.192.160.64/0.0.0.0/g' *
    

  • 更多用法,可以使用man sed命令来查看
  • 更新(2019-01-12):修改软连接文件
  • 更新(2019-03-07):批量替换
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值