Linux 流编辑器 | sed

sed 是个流编辑器,不同于常用的文本编辑器 vim,不会打开视觉缓冲区。

sed 在内存中创建一个模式空间,逐行输入文件内容,当有内容输入时,命令就会被执行,执行结果会打印到标准输出流,然后继续下一行输入。

标准输出流可以重定向到一个文件,也可以重定向到同一文件,用 --in-place=.bak

sed 没有交互模式,所以必须明确满足什么条件,执行什么操作

$ sed [OPTION]... {script-only-if-no-other-script} [input-file]...

先举个栗子

# 把 index.html 文件中,所有 http 替换成 https
$ sed -i 's/http/https/g' index.html

常用参数

上面的例子中,-i 表示就地编辑文件,除此之外常用的还有

  • -n 抑制自动打印,结合 p 打印特定行数据

  • -e 添加指定脚本到运行列表中

  • -f 添加指定脚本文件到运行列表中

  • -i 就地编辑文件,当前文件会修改成执行命令后的内容

  • -l 指定换行长度

  • -r 脚本中使用扩展正则表达式


常用命令

上面的例子中,'s/xxx/xxx/g' s 表示进行替换,g 表示行内进行全局替换。除此之外还有一些常用命令

  • d 删除满足条件的行

  • s 替换指定字符为另一个,可使用正则

  • g 在行内进行全局替换,结合 s

  • a\ 在当前行后面添加一行或多行,(例:'a------')

  • c\ 替换当前行的内容,(例:'c=====')

  • i\ 在当前行之前插入一行或多行

  • p 打印满足条件的行,结合 -n 只打印满足条件的行

  • 取反

  • w 将满足要求的行写入文件

  • r 从文件读入内容

  • y 替换字符串,不支持正则

  • n 处理当前行的下一行(next)


元字符集

^ 匹配行开始,如:/^sed/ 匹配所有以 sed 开头的行

$ 匹配行结束,如:/sed$/ 匹配所有以 sed 结尾的行

. 匹配一个非换行符的任意字符,如:/s.d/ 匹配 s 后接一个任意字符,最后是 d

* 匹配0个或多个字符,如:/*sed/ 匹配所有模板是一个或多个空格后紧跟 sed 的行

[] 匹配一个指定范围内的字符,如 /[sS]ed/ 匹配 sed 和 Sed

[^] 匹配一个不在指定范围内的字符,如:/[^A-RT-Z]ed/ 匹配不包含 A-R 和 T-Z 的一个字母开头,紧跟 ed 的行

\(..\) 匹配子串,保存匹配的字符,如 s/(love)able/\1rs,loveable 被替换成 lovers

& 保存搜索字符用来替换其他字符,如 s/love/ & /,love 这成 love

\< 匹配单词的开始,如: /<love/ 匹配包含以 love 开头的单词的行

\> 匹配单词的结束,如 /love>/ 匹配包含以 love 结尾的单词的行

x\{m\} 重复字符 x,m 次,如:/0{5}/ 匹配包含 5 个 0 的行

x\{m,\} 重复字符 x,至少 m 次,如:/0{5,}/ 匹配至少有 5 个 0 的行

x\{m,n\} 重复字符 x,至少 m 次,不多于 n 次,如:/0{5,10}/ 匹配 5~10 个 0 的行


常用形式

指定行

# 打印 test.txt 文件的第三行
# -n,抑制标准输出
# p,输出指定条件的内容
# 3,指文件第三行
$ sed -n '3p' test.txt
# 打印第 3 行到第 5 行的内容
$ sed -n '3,5p' test.txt
# 打印最后一行
# $,表示最后一行
$ sed -n '$p' test.txt

正则匹配

# 打印包含 .css 或 .js 的行,'\|' 前后不能有空格
$ sed -n '/.css\|.js/p' test.txt
# 正则匹配到的内容进行替换
$ sed -r 's/^([^\[]*)\[/\[/g' test.txt

排除指定行

# 排除包含'ha'的行
$ sed '/ha/d' test.txt
# 排除包含'ha'的行
$ sed -n '/ha/!p' test.txt

分别替换多个字符串

# 文件中所有英文格式的月份替换成数字格式
$ sed -e 's/Jan/01/g' -e 's/Feb/02/g' -e 's/Mar/03/g' -e 's/Apr/04/g' -e 's/May/05/g' -e 's/Jun/06/g' -e 's/Jul/07/g' -e 's/Aug/08/g' -e 's/Sep/09/g' -e 's/Oct/10/g' -e 's/Nov/11/g' -e 's/Dec/12/g' test.txt
# 分别替换 you 和 hello
# 多个命令用分号隔开
$ sed 's/you/me/ ; s/hello/world/' test.txt

大小写转换

# 第 2 次匹配到 HELLO 时,转换为小写
# \L&,表示小写
$ sed 's/HELLO/\L&/2' test.txt
# 匹配到的所有 world 转换为大写
$ sed 's/world/\U&/g' test.txt

收集操作行

# 匹配到的所有 world 转换为大写,并把转换的行存入 sed.log 文件
$ sed 's/world/\U&/gw sed.log' test.txt

花括号限定范围

# 只把第 3 行的 ha 转换为大写
$ sed '3 {s/ha/\U&/}' test.txt
# 匹配到 HELLO 后,到下一行,把 World 转转为小写
$ sed '/HELLO/{n ; s/World/\L&/}' test.txt

从文件中读入字符串

# 从 input.txt 中读取内容,放在 hello 匹配行的后面
$ sed '/hello/r input.txt' test.txt


最近用到的 apache log 内容集计分析的命令

cat ./*/* | sed '/ELB-HealthChecker/d' | sed '/.jpg\|.gif\|.css\|.js/d'| sed -r 's/^([^\[]*)\[/\[/g' | cut -c 2-21 | sed -e 's/Jan/01/g' -e 's/Feb/02/g' -e 's/Mar/03/g' -e 's/Apr/04/g' -e 's/May/05/g' -e 's/Jun/06/g' -e 's/Jul/07/g' -e 's/Aug/08/g' -e 's/Sep/09/g' -e 's/Oct/10/g' -e 's/Nov/11/g' -e 's/Dec/12/g' | sed 's/\(..\)\/\(..\)\/\(....\):\(..\):\(..\):\(..\)/\3\/\2\/\1:\4:\5:\6/g' | sort | uniq -c > res.txt

还有很多高级用法,用到再慢慢补充

posted @ 2023-04-12 17:20  菜乌  阅读(61)  评论(0编辑  收藏  举报