6. sed
sed(Stream Editor,流编辑器),利用脚本处理文本文件。
参数:
- -i
直接修改文件内容(默认输出到控制台,不改变原文件)。
- -e <script>
以选项中指定的 script 来处理输入的文本文件。
- -f <script文件>
以选项中指定的 script 文件来处理输入的文本文件。
- -h
显示帮助。
- -n
仅显示 script 处理后的结果。
- -V
显示版本信息。
- -E
扩展 sed,可以使用扩展正则表达式
动作:
a
追加
c
替换行
d
删除
i
插入
p
打印
s
替换
6.1. 正则表达式基础
sed 支持的正则表达式和 grep 类似,也分为基本正则和扩展正则。下面列举几个基本正则字符:
^
表示一行的开头,如:^#
表示以#
开头的匹配。$
表示一行的结尾,如:}$
表示以}
结尾的匹配。\<
表示词首,如:\<abc
表示以abc
为首的词。\>
表示词尾,如:abc\>
表示以abc
结尾的词。.
表示任何单个字符。*
表示某个字符出现了 0 次或多次。[ ]
表示字符集合,如:[abc]
表示匹配a
或b
或c
,[a-zA-Z]
表示匹配所有的26个字母;^
表示取反,如[^a]
表示非a
的字符。
6.2. 匹配与替换
单个匹配
sed "s/^/#/g" foo.txt
:在行首加 #。sed "3s/my/your/g" foo.txt
:只在第3行替换。sed "3,6s/my/your/g" foo.txt
:在第3行至第6行替换(闭区间),逗号后面没有空格。sed "s/my/your/1g" foo.txt
:替换每行的第一个匹配。sed "s/my/your/2g" foo.txt
:替换每行的第二个匹配。sed "s/my/your/g" foo.txt
:替换每行的所有匹配。sed "s/my/*&*/g" foo.txt
:使用&
来指代需要替换的模式,可以方便地在其周围增加其他字符(*my*
)。sed -E "s/(.*), (.*)/\2, \1/g" foo.txt
:-E
使用扩展正则表达式;\1
和\2
表示捕获匹配。
一个例子
html.txt:
<b>This</b> is what <span style="text-decoration: underline;">I</span> meant. Understand?
目标:去掉 html.txt 中所有的 <*>
。
sed "s/<.*>//g" html.txt
结果:meant. Understand?
(开头有空格)。
sed "s/<[^>]*>//g" html.txt
结果:This is what I meant. Understand?
。[^>]
表示除>
之外的字符集合。
如果指令使用双引号,碰到需要替换单引号的情况可以不对单引号使用转义符号。
多个匹配
下面两个命令等价:第1-3行把 my
替换为 your
,从第3行开始把 This
替换为 That
。
sed '1,3s/my/your/g; 3,$s/This/That/g' foo.txt
sed -e '1,3s/my/your/g' -e '3,$s/This/That/g' foo.txt
Note
上面的指令使用的是单引号,双引号和 3,$
类似的模式搭配会报错。
圆括号匹配
圆括号括起来的正则表达式所匹配的字符串可以当成变量来使用,通过 \1
,\2
……来解引用变量。
foo.txt:
1This is my cat, my cat's name is betty
2This is my dog, my dog's name is frank
3This is my fish, my fish's name is george
4This is my goat, my goat's name is adam
sed "s/This is my \(.*\),.*is \(.*\)/\1:\2/g" foo.txt
得到:
1cat:betty
2dog:frank
3fish:george
4goat:adam
6.3. 动作
a 和 i
sed "1 i This is my monkey, my monkey's name is wukong" foo.txt
在第一行之前插入sed "$ a This is my monkey, my monkey's name is wukong" foo.txt
在最后一行之后追加sed "/my/a ----" foo.txt
在匹配到my
的每一行之后追加----
c
sed "2 c This is my monkey, my monkey's name is wukong" foo.txt
对第二行替换sed "/fish/c This is my monkey, my monkey's name is wukong" foo.txt
对匹配到fish
的行进行整行替换
d
sed "2d" foo.txt
删除第二行sed '2,$d' foo.txt
删除第二行及之后的行sed "/fish/d" foo.txt
删除匹配到fish
的行
p
打印,搭配参数 -n
使用,只打印匹配的行,否则会打印所有的行以及匹配的行。
sed -n '/fish/p' foo.txt
打印匹配到fish
的行sed -n '/dog/,/fish/p' foo.txt
打印匹配到dog
和fish
之间的行sed -n '1,/fish/p' foo.txt
从第一行打印到匹配fish
的行
6.4. 参考资料
sed, a stream editor
Linux sed 命令
SED 简明教程
How And When To Use The Dot Command In Bash?