sed
是 stream editor
的简称, 是一个流编辑器。它逐行处理输入文本, 处理时, 把当前处理的行存储在临时缓冲区中, 称为 "pattern space"
, 接着用 sed
命令处理缓冲区中的内容, 处理完成后, 把结果输出到标准输出。接着处理下一行, 这样不断重复, 直到文件末尾。
基本语法
# 命令选项 sed 操作命令 要处理的文件
sed [option] 'command' input_file
常用选项
-n 使用安静 silent 模式。在一般 sed 的用法中, 所有来自 stdin 的内容一般都会被列出到屏幕上。但如果加上 -n 参数后, 则只有经过 sed 特殊处理的那一行 (或者动作) 才会被列出来
-e 多点编辑, 可以执行多个子命令
-f 从文件中读取 sed 命令, -f filename 则可以执行 filename 内的 sed 命令
-r 让 sed 命令支持扩展的正则表达式 (默认是基础正则表达式)
-i 直接修改文件内容, 不仅仅是输出
-l 指定每行的最大长度
常用命令
实验用文件内容 test.txt
letitia
mail
uuencode
1003605091
01566
a
命令 - 新增
在指定行后追加文本 (多行字符串可以用 \n
分隔), 而这些字串会在新的一行出现
从第一行到最后一行所有行后追加 "add one"
字符串
sed '1,$a\add one' test.txt
letitia
add one
mail
add one
uuencode
add one
1003605091
add one
01566
add one
在匹配到 mail
行后追加 "add one"
字符串
sed '/mail/a\add one' test.txt
letitia
mail
add one
uuencode
1003605091
01566
i
命令 - 插入
在匹配的行前面插入字符串行, 这些字串会在新的一行出现
在第二行之前插入一行内容 "inserted text"
sed '2i\inserted text' test.txt
letitia
inserted text
mail
uuencode
1003605091
01566
c
命令 - 替换整行
用于替换整行内容
将第二行替换为 This is a new line
sed '2cThis is a new line' test.txt
letitia
This is a new line
uuencode
1003605091
01566
从第一行到最后一行所有行替换为 "add one"
字符串
sed '1,$c\add one' test.txt
add one
将匹配到 mail
行替换为 "add one"
字符串
sed '/mail/c\add one' test.txt
letitia
add one
uuencode
1003605091
01566
s
命令 - 替换文本
用于在行内替换指定的文本内容
基本格式
sed '位置参数 s/要查找的文本/替换后的文本/[flag]'
将所有的 apple
替换为 orange
echo "I have an apple" | sed 's/apple/orange/'
I have an orange
将所有的 letitia
替换为 new
sed 's/letitia/new/g' test.txt
new
mail
uuencode
1003605091
01566
{}
要转义, 因为此处使用的不是扩展正则表达式
sed 's/[0-9]\{10\}/miss letitia/g' test.txt
letitia
mail
uuencode
miss letitia
01566
将前两行里的 l
替换为 L
sed '1,/^ma/ s/l/L/g' test.txt
Letitia
maiL
uuencode
1003605091
01566
这个例子比较复杂。使用大括号, 表示对 1 到 3 行做了一组操作
sed -n '1,3{
s/l/L/g
s/e/E/g
2 i tyrone
p
}' test.txt
LEtitia
tyrone
maiL
uuEncodE
d
命令 - 删除
删除指定行
删除第三行
sed '3d' test.txt
letitia
mail
1003605091
01566
从第四行到最后一行全部删除
sed '4,$d' test.txt
letitia
mail
uuencode
p
命令 - 打印
打印指定行
打印第一至第三行
sed '1,3 p' test.txt
letitia
letitia
mail
mail
uuencode
uuencode
1003605091
01566
打印第一至第三行有 -n
参数
sed -n '1,3p' test.txt
letitia
mail
uuencode
观察输出结果, 不使用 -n
选项时, sed 命令把 1 到 3 行输出了两次。这是因为不使用 -n
时, sed 首先读取一行, 并默认将缓冲区内的文本输出出来, 之后 p
子命令再次输出。使用 -n
时, 默认输出取消, 只有 p
子命令的输出结果
sed 命令支持正则表达式定位。语法为 /re/
, re 表示正则表达式
打印出从匹配正则表达式的地方到第 5 行, 也就是从匹配以 ma
开头的文本行处开始
sed -n '/^ma/,5 p' test.txt
mail
uuencode
1003605091
01566
以 first
开头 end
结尾的所有行全部打印
sed -n '/^first.*end$/p' test.txt
1~2
表示从第一行开始, 行号递增 2 输出, 即输出奇数行。语法格式为 first~step
sed -n '1~2 p' test.txt
letitia
uuencode
01566
标志选项
g # 全局匹配, 会替换文本行中所有匹配的字符串
digit # 替换文本行中第 n 个 (digit 是 1 至 9) 匹配的字符串
p # 若发生了替换操作, 并且将缓冲区输出到标准输出
w file-name # 若发生了替换操作, 并且将改动的行输出到磁盘文件中
i # 表示进行 Regexp 匹配时, 不区分大小写字母
GNU 版本的扩展标识
\digit # Replacement 中可含有后向引用中的 \digit (digit 是 1 至 9), 引用前面定义的子表达
& # 代表模版空间中的整个匹配部分
\L # 将在其后的替换部分转换成小写字母, 直到发现一个 \U 或 \E, GNU 扩展功能
\l # 将下一个字符转换成小写字母, GNU 扩展功能
\U # 将在其后的替换部分转换成大写字母, 直到发现一个 \L 或 \E, GNU 扩展功能
\u # 将下一个字符转换成大写字母, GNU 扩展功能
\E # 停止由 \L 或 \U 指示开始的大小写转换, GNU 扩展功能
基本正则表达式
元字符 | 说明 |
---|---|
* |
将 * 前面的正则表达式匹配的结果重复任意次 (含 0 次) |
\+ |
与星号 (* ) 相同, 只是至少重复 1 次, GNU 的扩展功能 |
\? |
与星号 (* ) 相同, 只是最多重复 1 次, GNU 的扩展功能 |
\{i\} |
与星号 (* ) 相同, 只是重复指定的 i 次 |
\{i,j\} |
与星号 (* ) 相同, 只是重复 i 至 j 次 |
\{i, \} |
与星号 (* ) 相同, 只是至少重复 i 次 |
\(regexp\) |
将 regexp 看作一个整体, 用于后向引用, 与 \digit 配合使用 |
. |
匹配任意单个字符 |
^ |
匹配模版空间开始处的 NULL 字符串 |
$ |
匹配的是模版空间结束处的 NULL 字符串 |
[list] |
匹配方括号中的字符列表中的任意一个 |
[^list] |
否定匹配方括号中的字符列表中的任意一个 |
regexp1|regexp2 |
用在相邻的正则表达式之间, 表示匹配这些正则表达式中任一个都可以。匹配是从左向右开始的, 一旦匹配成功就停止匹配 |
regexp1regexp2 |
匹配 regexp1 和 regexp2 的连接结果 |
\digit |
匹配正则表达式前半部分定义的后向引用的第 digit 个子表达式。digit 为 1 至 9 的数字, 1 为从左开始 |
\n |
匹配换行符 |
\meta |
将元字符 meta 转换成普通字符, 以便匹配该字符本身, 有$ 、* 、. 、[ 、\ 和 ^ |
扩展正则表达式
它们之间的差别很小, 那就是转义字符的使用
简称 | 全称 | 解释 |
---|---|---|
BRE | basic regular expressions | 基础正则表达式 (过时的) |
ERE | extended regular expressions | 扩展正则表达式 (现代的) |
如果从字面理解, 基础这个字眼让 BRE 显得具有一定地位, 但实质上 BRE 的存在只是为了兼容一些老旧的软件。
基本正则表达式 | 扩展正则表达式 |
---|---|
\? |
? |
\+ |
+ |
\| |
| |
\{ \} |
{ } |
\( \) |
( ) |
常用转义字符
转义字符 | 说明 |
---|---|
\a |
匹配一个 BEL 字符 |
\f |
匹配一个换页字符 |
\n |
匹配一个换行字符 |
\r |
匹配一个回车字符 |
\t |
匹配一个水平 Tab 字符 |
\v |
匹配一个垂直 Tab 字符 |
\cX |
匹配 Control+X , X 是任意字符 |
\dXXX |
匹配一个 ASCII 码是十进制 XXX 的字符 |
\oXXX |
匹配一个 ASCII 码是八进制 XXX 的字符 |
\xXX |
匹配一个 ASCII 码是十六进制 XX 的字符 |
\w |
匹配任意一个单词字符 (字母、数字和下划线) |
\W |
匹配任意一个非单词字符 |
\b |
匹配一个单词的边界符: 字符的左边是一个单词字符, 并且右边是一个非单词字符, 反之亦然 |
\B |
匹配除单词边界符外所有字符: 字符的左边和右边同时是单词字符或非单词字符 |
原文