1 功能

stream editor.

2 模式空间

2.1 模式空间

一块活动缓冲区,在sed执行命令时会保存每一个操作文本对象。

2.2 保持空间

用于临时保存文本对象,相对于pattern space,hold space是一个中间变量

1
2
3
4
5
6
7
h          PS拷贝到HS中
H PS附加到HS中

g HS拷贝到PS中
G HS附加到PS中

x 交换HS和PS之间的内容

2.3 流程

简易流程:

process

处理流程

handle

3 Command

3.1 Format

1
2
sed OPTIONS COMMAND  files
sed OPTIONS SCRIPT INPUTFILES

3.2 Options

1
2
3
4
5
6
7
8
9
-n                    进行安静打印,不输出冗余信息,和substitude中FLAGS(p)联合使用;
-e script 添加脚本到程序的运行列表,可以跟随多个替换方案;
-f script-file 用file替换script,从文件中读取命令,多个-e的替换方案;
-i 直接修改匹配项,不用进行重定向(不能和-n联用,否则会造成目标文件为空)

-r 在脚本中使用扩展正则表达式
-s 将输入文件视为各个独立的文件而不是一个长的连续输入
-u (--unbuffered)从输入文件读取最少的数据,更频繁的刷新输出
PS:如果没有-e/-f,第一个非选项参数视为sed脚本,如果没有输入文件,默认从stdin读取

4 文本操作命令

4.1 替换命令

substitude:‘s/regexp/replacement/flags’(文本模式过滤器,见下面说明)

flags说明:

1
2
3
4
g—— Apply the replacement(替换、代替) to all matches to the regexp, not just the first.
number—— Only replace the numberth match of the regexp.不过在很多用法无效哦,例如vim中;
p——如果替换发生, then print the new pattern space.一般和-n一起连用,仅仅打印替换行信息;
w——如果替换发生, then write out the result to the named file.格式:s/regexp/replacement/w resultFile

4.2 删除命令

1
2
3
4
5
6
7
命令:d
功能:删除匹配的行
格式:数字范围过滤、文本模式过滤

命令:D
功能:多行删除命令,仅删除模式空间中到\n为止的所有字符(即第一行)
产生原因:N和d混用,可能出现误删操作,见下面的例子

4.3 插入和附加命令

1
2
3
4
5
命令:i/a
功能:插入(在指定行前增加新行),附加(在指定行后增加新行)
格式:
sed '[address]command\
new line' inputfile

4.4 修改命令

1
2
3
命令:c
功能:修改数据流中的整行内容
格式:同插入、附加命令

4.5 转换命令

1
2
3
4
5
命令:y(transform)
功能:将同等长度的字符串替换为同等长度的另外一个字符串
格式:
sed '[address]/inchars/outchars/' intputfile
PS:inchars和outchars必须相等

4.6 打印命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
命令:p
功能:打印文本行,与-n连用
格式:数字范围过滤、文本模式过滤

命令:P
功能:多行打印命令,仅打印模式空间中到\n为止的所有字符(即第一行)
使用:常常和D、N一起使用,便利输出整个文本(D命令)

命令:=
功能:打印行号
格式:数字范围过滤、文本模式过滤

命令:l
功能:列出行
格式:数字范围过滤、文本模式过滤

4.7 多行命令

1
2
3
4
5
命令:n
功能:默认方式,单行上的处理,基于\n将输入流分成行

命令:N
功能:将数据流中的两个文本行合并到同一个模式空间中(包含\n换行)

4.8 排除命令(非)

1
2
3
命令:!
功能:使当前命令不要作用于指定的特定地址或者区间,但是会作用于该区间之外的地址
格式:!command

5 本身操作(改变流)

5.1 命令跳转(if)

1
2
3
命令:b(branch)
功能:类似C代码,调到command集合中指定的label处,循环操作
格式:[address]b [label]

5.2 命令测试(if)

1
2
3
命令:t
功能:基于上一条命令是否匹配,成功匹配则跳过下一条command
格式:[address]t [label]

6 重要知识点

6.1 address的使用

格式:

1
2
3
4
5
6
7
[address]command
或者
[address]{
command1
command2
...
}

数字范围过滤:

1
2
3
first,second         first到second
$ 最后一行
first, ~N first到first+N

文本模式过滤:

1
2
/pattern/command
/p1/,/p2/command p1到p2之间的所有文本

地址区间:

1
2
3
number               单一行号
first~step 指定开始行和step
first, +N first开始的N行

6.2 组合命令和地址区间

在模式空间对象上执行多条命令,格式见上面的address介绍, 见文本过滤模式中的第二条。

6.3 分组概念

功能:替代整个匹配模式, 匹配单独的单词或者子串,见正则表达式

7 Example

7.1 删除

1
2
3
4
5
6
7
8
9
10
11
#删除第二行到最后一行
sed '2,$d' test.txt
# 删除所有包含以'bifeng'开头的行
sed '/^bifeng/d' test.txt
# 删除first到second之间所有串(单行)
sed '/first/, /second/d' test.txt

# 删除多行匹配中的第一行
sed 'N ; /first\nSecond/D' test.txt
# 删除多行匹配中的两行
sed 'N ; /first\nSecond/d' test.txt

7.2 打印

1
2
3
4
5
6
7
8
9
10
11
12
#查询包括关键字ruby所在起始的所有行,其他不打印
sed -n '/^ruby/p' test.txt
#查询‘空行’的所在行号
sed -n '/^$/=' test.txt
# 打印数据流中的文本和不可打印的ASCII(用八进制)
sed -n 'l' test.txt

# 遍历打印整个文本
sed -n '{
N
P
D}' file

PS:D命令每次执行完后会自动返回脚本(命令脚本)的起始处

7.3 插入/附加

1
2
3
4
#第一行后增加字符串"drink tea"
sed '1a drink tea' test.txt
# 第一行前插入
sed '1i drink tea' test.txt

7.4 替换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 递归替换所有内容
grep -r -l "lagou" .|xargs sed -i "s/lagou/kuang/g"
# 替换文件中的中文乱码(游离的\302)
sed -i 's/\o240\|\o302//g' crypt-aes.c
# 替换并更新当前文件
grep "/home/xinshu/" -r -l .|xargs sed -i -e "s/\/Users\/bamboo\//\/Users\/zhengbifeng\//g"
# 替换并将之前文件备份
grep "/home/xinshu/" -r -l .|xargs sed -ibk -e "s/\/home\/xinshu\//\/Users\/bamboo\//g"

# MAC上替代, 使用正则, 替换行: date: 2018-03-18T16:14:29+08:00 为 time: 2018-03-18 16:14:29
grep "date:" -r -l languages| xargs sed -i -e -E 's/date: (.*)T(.*)\+08:00/time: \1 \2/g'
# 使用egrep替代所有time: 2018-03-18 16:14:29为date: 2018-03-18 16:14:29
egrep "time:( [0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2})" -r -l . | xargs \
sed -i -e -E 's/time: ([0-9]{4}-[0-9]{2}-[0-9]{2}) ([0-9]{2}:[0-9]{2}:[0-9]{2})/date: \1 \2/g'

注意, 在MacOS上, 需要在每一个sed命令前面增加: LC_ALL=C

错误:

1
2
3
4
5
6
# 错误
(Error: illegal bytes)
# 原因
sed在识别含有"多字节编码"遇到解析冲突问题, 需要手动更改语言编码环境, 让 MAC正确处理单字节和多字节,但是不建议覆盖本地 Locale.
# 错误解决
export LC_CTYPE=C ; export LANG=C; + 具体的替换操作命令

7.5 修改/转换

1
2
3
4
5
# 修改第三行
sed '3c This is a changed line of text' file

# 将first转为12345
sed '3y/first/12345/' first

7.6 跳转/测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 如果匹配,则跳转到指定标签
sed '{
/first/b jump1
s/This is the/No jump on/

:jump1
s/This is the/Jump here on/}' file2

# 如果匹配,执行完当前命令后,跳过下一条命令
sed '{
s/first/matched/
t

s/This is the/No match on/
}' file2

7.7 高级例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 加倍行间距,其中$!表示不对最好一行操作
sed '$!G' data2

# 加倍行间距,如果有连续空白行,则视为一个
sed '{
/^$/d
$!D}' file1

# 显示末尾的若干行
sed '{
:start
$q
N
11,$D
b start}' file1