sed(Strem Editor)本质上是一个编辑器,但是它是非交互式的,这点与VIM不同;同时它有事面向字符流的,输入的字符流经过sed处理后输出。这两点特性使得sed成为命令行下非常有用的文本处理工具。
一、sed基础
- 1.1 使用gnu-sed替换macOS下sed
mac自带的sed工具与linux下的gnu-sed使用上有所区别,比如mac下通过sed -i xxx
直接修改文件时候必须指定备份文件名(可为空字符串),想使用linux下的sed则需安装gnu-sed
brew install gnu-sed
查看sed版本
sed --version
---
gsed (GNU sed) 4.7
Copyright (C) 2018 Free Software Foundation, Inc.
...
打印sed简要帮助信息
sed --help
- 1.2 sed基本语法
sed命令的基本语法如下:
sed [options] script [filename]
其中options是sed提供的命令行参数,script是需要对输入执行的一个或多个操作指令,sed会一次读取输入文件的每一行到缓存中执行指令,因此不会影响源文件。script中每条指令由pattern和procedure两部分组成,pattern一般为用’/'分隔的正则表达式(sed中也可能是行号),procedure则是一串编辑指令。
- 1.3 sed的处理流程
- a.读取新的一行内容到缓存空间
- b.从指定的操作指令中取出提一条指令,判断是否匹配pattern
- b1.如果不匹配,则忽略后续的编辑命令,回到b继续取出下一条命令
- b2.如果匹配,则针对缓存行执行编辑命令,之后回到b继续取出下一条命令
- c.当所有指令都应用后,输出缓存行的内容,之后回到a继续读入下一行内容
- d.当所有行都处理完毕,结束
构造一个测试文件:
cat sedtest.txt
---
Jerry, 22, PEK
Lucy, 21, SHA
Lily, 23, CAN
Amy, 22, SZX
Angel, 20, TSA
将文本中PEK替换为beijing、TSA替换为taibei:
sed -e 's/PEK/beijing/' -e 's/TSA/taibei/' sedtest.txt
---
Jerry, 22, beijing
Lucy, 21, SHA
Lily, 23, CAN
Amy, 22, SZX
Angel, 20, taibei
命令行操作单个指令时-e是可选项,操作多个指令时可以变化操作形式去除-e,以上语句等同于:
sed 's/PEK/beijing/;s/TSA/taibei/' sedtest.txt
- 1.4 地址匹配
sed命令中可以包含0个、1个或2个地址(地址对),地址可以是正则表达式、行号或特殊行的符号(如$表示最后一行)
a.如果没有指定地址,默认将编辑命令应用到所有行
b.如果指定一个地址,则将编辑命令应用到具体匹配到的行
c.如果指定一个地址对(a1,a2),则将编辑命令应用到地址对包含的所有行中
e.如果地址后有非(!),则将编辑命令应用到不匹配到该地址的所有行
sed 'd' sedtest.txt // 删除所有行
---
sed '1d' sedtest.txt //删除第一行
---
Lucy, 21, SHA
Lily, 23, CAN
Amy, 22, SZX
Angel, 20, TSA%
sed '2,$d' sedtest.txt //删除第二行到最后一行
---
Jerry, 22, PEK
sed '/Lily/d' sedtest.txt //删除包含Lily的行
---
Jerry, 22, PEK
Lucy, 21, SHA
Amy, 22, SZX
Angel, 20, TSA
sed '/Lily/,/Angel/d' sedtest.txt //删除两个正则匹配间的所有行
---
Jerry, 22, PEK
Lucy, 21, SHA
sed '2,/Angel/d' sedtest.txt //删除第二行到匹配到Angel的行
---
Jerry, 22, PEK
sed '/Lucy/!d' sedtest.txt //删除除包含Lucy外的所有行
---
Lucy, 21, SHA
sed '/Lily/,+2d' sedtest.txt. //删除包含Lily的行及其后的2行
---
Jerry, 22, PEK
Lucy, 21, SHA
sed '/Lucy/~2d' sedtest.txt //删除包含Lucy的行及其倍数行后的行
---
Jerry, 22, PEK
Angel, 20, TSA
sed '1~2d' sedtest.txt //从第一行开始,没两行删除一行
---
Lucy, 21, SHA
Amy, 22, SZX
对于(a1,a2) 这样的地址对的形式,执行过程为:1.如果a1匹配成功,则处理开关打开,在该行上执行命令;2.读入下一行,判断a2是否匹配,如果a2在a1前则不匹配,处理开关关闭。如果a2匹配成功,则执行命令,处理开关关闭。如果a2在a1后,则一直处理到匹配为止(如果a2一直不匹配则处理到最后一行)。因此,如果a2<a1时的,如果a1匹配成功命令会只处理a1匹配的这行
sed '2,1d' sedtest.txt
---
Jerry, 22, PEK
Lily, 23, CAN
Amy, 22, SZX
Angel, 20, TSA
- 1.5 sed编辑指令
sed的编辑指令有两种约定,其中[address]指任意地址或地址对,[line-address]指只能是单个地址:
[address]command
[line-address]command
sed编辑命令如下:
命令 | 名称 | 语法 | 说明 | 示例 |
---|---|---|---|---|
s | 替换 | [address]s/pattern/replacement/flags | 替换匹配的内容(flag取值范围,n:替换前n个pattern;g:替换所有pattern;p:匹配时打印内容;w:匹配pattern时输出到指定文件,空默认为替换第一个pattern) | sed '1,5s/PEK/beijing/g' sedtest.txt |
d | 删除 | [address]d | 删除匹配的行 | sed '2,$d' sedtest.txt |
i | 插入 | [line-address]i\text | 在匹配的行前插入文本 | sed '1i\hehe' sedtest.txt |
a | 追加 | [line-address]a\text | 在匹配的行后插入文本 | sed '1a\hehe' sedtest.txt |
c | 行替换 | [adress]c\text | 将匹配的行替换成文本 | sed '2c\hehe' sedtest.txt |
p | 行打印 | [address]p | 打印模式空间中的行 | sed -n '1p' sedtest.txt |
= | 打印行号 | [address]= | 打印匹配到的行的行号 | sed '=' sedtest.txt |
y | 字符转换 | [address]y/SET1/SET2 | 将匹配行的SET1字符替换为SET2中字符 | sed 'y/ABCE/abce/' sedtest.txt |
n | 读取下一行 | [address]n | 将下一行的内容读取到模式空间 | echo -e "1\n2" |sed -n 'n;p' |
q | 退出 | [line-address]q | 读取到匹配的行后退出 | sed 'q' sedtest.txt |
N | 读取下一行 | [address]n | 读取下一行到模式空间,并以回车\n连接 | sed '/PEK/{N;s/PEK\nLucy/location/}' sedtest.txt |
D | 删除模式空间第一行内容 | [address]D | sed '/^$/{N;/\n$/D}' sedtest.txt | |
P | 打印模式空间的第一行内容 | [address]P | sed -n 'N;/SHA/P' sedtest.txt | |
h/H | 保存 | h/H | 将模式空间的内容复制/追加到保持空间 | sed 'h' sedtest.txt |
g/G | 取回/追加到模式空间 | g/G | 将保持空间的内容复制/追加到模式空间 | sed 'G' sedtest.txt |
x | 交换 | x | 交换模式空间和保持空间内容 | sed ‘x’ sedtest.txt |
- 1.6 sed主要option选项功能
option | 功能描述 |
---|---|
-n | 抑制默认输出 |
-e | 执行编辑命令 |
-f | 指定脚本文件 |
-i | 在源文件上修改并取代源文件 |
-s | 让sed将各文件分开单独处理。默认情况下处理多个输入文件时一般会合并成一个文件来处理 |
-r | 切换使用扩展的正则表达式 |
使用示例
sed -n '1,2p' sedtest.txt
---
Jerry, 22, PEK
Lucy, 21, SHA
sed -e 's/PEK/beijing/' sedtest.txt
---
Jerry, 22, beijing
Lucy, 21, SHA
Lily, 23, CAN
Amy, 22, SZX
Angel, 20, TSA
cat script.sed
---
s/PEK/beijing/
s/TSA/taibei/
sed -f script.sed sedtest.txt
---
Jerry, 22, beijing
Lucy, 21, SHA
Lily, 23, CAN
Amy, 22, SZX
Angel, 20, taibei
sed -i '/^$/d' sedtest.txt // 删除空行
sed -s 's/PEK/beijing/;y/ABC/abc/' sedtest.txt sedtest1.txt
---
Jerry, 22, beijing
Lucy, 21, SHa
Lily, 23, caN
amy, 22, SZX
angel, 20, TSa
111, aaa
222, bbb
sed -r 's/ {2,}/ /g' sedtest.txt. //合并空格
二、常用sed命令
- 2.1 组合命令
sed中可以用{}来组合命令:
sed '1,5{y/ABCDE/abcde/;s/SZX/shenzheng/}' sedtest.txt
---
Jerry, 22, PeK
Lucy, 21, SHa
Lily, 23, caN
amy, 22, shenzheng
angel, 20, TSa
- 2.2 添加/删除空白行
在行后添加空白行,Get命令是将保留空间的内容去除并添加到当前模式空间的内容后,当保留空间为空时效果是往模式空间添加一行空行:
sed -i '/PEK/G' sedtest.txt
在行前添加空白行,x的意思是交换保留空间和模式空间的内容:
sed -i '/TSA/{x;p;x}' sedtest.txt
删除空白行:
sed -i '/^$/d' sedtest.txt
- 2.3 合并连续重复的字符
echo 'print hello, world !' | sed -r 's/ {2,}/ /g'
- 2.4 在每一行开头添加行号
sed '=' sedtest.txt | sed 'N;s/\n/\t/'
- 2.5 pattern引用及行首匹配
对于/regexp/s/regexp/replacement/可以省略pattern部分,
sed '/PEK/{s//&("ing")/;s/^/+ /}' sedtest.txt
---
+ Jerry, 22, PEK("ing")
Lucy, 21, SHA
Lily, 23, CAN
Amy, 22, SZX
Angel, 20, TSA
- 2.6 删除偶数行
指令n的意思是读入下一行,并且输出当前行,这里读入下一行并将其删除:
sed 'n;d' sedtest.txt
---
Jerry, 22, PEK
Lily, 23, CAN
Angel, 20, TSA
- 2.7 每2行添加一个空行
sed '0~2G' sedtest.txt
---
Jerry, 22, PEK
Lucy, 21, SHA
Lily, 23, CAN
Amy, 22, SZX
Angel, 20, TSA
- 2.8 统计行数
使用-n抑制输出,并只在最后一行打印行号
sed -n '$=' sedtest.txt
---
5
- 2.9 将两行合并成一行
$!N表除最后一行外,其它每行在读入时将下一行读进来添加到行后,用空格替换换行符:
sed '$!N;s/\n/ /' sedtest.txt
---
Jerry, 22, PEK Lucy, 21, SHA
Lily, 23, CAN Amy, 22, SZX
Angel, 20, TSA
- 2.10 读取文件前x行
sed '2q' sedtest.txt
---
Jerry, 22, PEK
Lucy, 21, SHA
- 2.11 读取文件第x行
sed '2q;d' sedtest.txt
---
Lucy, 21, SHA
- 2.12 删除文本中多余的空行,保留一行
D只会删除模式空间第一行,当读入匹配第一个空行时$,N读取下一行内容,此时匹配^\n$导致第一行被删除。现在模式空间是空的,重新执行命令,N读取下一行,如果下一行仍然为空,则仍然匹配\n$并删除第一行,如果下一行不为空则该空行不删除,因此会保留每次连续的最后一个空行。
sed '/^$/{N;/\n$/D}' sedtest.txt
---
Jerry, 22, PEK
Lucy, 21, SHA
Lily, 23, CAN
Amy, 22, SZX
Angel, 20, TSA