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
还有很多高级用法,用到再慢慢补充