sed是一种流编辑器,以行为单位进行文本处理,可以将数据行进行替换、删除、新增、选取等操作。
sed 一次从文件中读一行,并且将这一行放到sed的工作车间(pattern space),在工作车间处理完毕后,将结果输出到标准输出,其间并不会动原文件的内容
语法如下:
sed [options] 'command' file(s)
接下来以诗仙李白写给杨贵妃的清平调为素材
$ cat 清平调.txt
其一
云想衣裳花想容,春风拂槛露华浓
若非群玉山头见,会向瑶台月下逢
其二
一枝红艳露凝香,云雨巫山枉断肠
借问汉宫谁得似,可怜飞燕倚新妆
其三
名花倾国两相欢,长得君王带笑看
解释春风无限恨,沉香亭北倚阑干
匹配内容
p
匹配内容有个很有意思,会将匹配到的数据输出两遍,未匹配的行输出一遍,这个设定基本没卵用,因此要加上-n
参数,就能屏蔽到未匹配到的行数
- 输出前三行数据
$ sed '1,3p' 清平调.txt # 结果是匹配到的前三行数据会输出两遍,未匹配到的会输出一遍
$ sed -n '1,3p' 清平调.txt # 只输出匹配到的前三行数据,符合我们的预期
其一
云想衣裳花想容,春风拂槛露华浓
若非群玉山头见,会向瑶台月下逢
- 输出以
其
开头的行
$ sed -n '/^其/p' 清平调.txt
其一
其二
其三
行定位
- 定位一行
$ sed -n '5p' 清平调.txt
一枝红艳露凝香,云雨巫山枉断肠
$ nl 清平调.txt | sed -n '5p'
5 一枝红艳露凝香,云雨巫山枉断肠
- 定位多行
$ nl 清平调.txt | sed -n '4,6p' # 指定行数
4 其二
5 一枝红艳露凝香,云雨巫山枉断肠
6 借问汉宫谁得似,可怜飞燕倚新妆
$ nl 清平调.txt | sed -n '/其一/,/其二/p' # 指定内容,匹配从其一至其二的行
1 其一
2 云想衣裳花想容,春风拂槛露华浓
3 若非群玉山头见,会向瑶台月下逢
4 其二
- 反向匹配
$ nl 清平调.txt | sed -n '1,6!p' # 匹配除了第1至6行之外的行
7 其三
8 名花倾国两相欢,长得君王带笑看
9 解释春风无限恨,沉香亭北倚阑干
- 间隔行
$ nl 清平调.txt | sed -n '1~2p' # 从第1行开始,步长为2,即打印所有奇数行
1 其一
3 若非群玉山头见,会向瑶台月下逢
5 一枝红艳露凝香,云雨巫山枉断肠
7 其三
9 解释春风无限恨,沉香亭北倚阑干
新增行
$ nl 清平调.txt | sed '3a==============' # 在第3行后面新增数据
1 其一
2 云想衣裳花想容,春风拂槛露华浓
3 若非群玉山头见,会向瑶台月下逢
==============
4 其二
5 一枝红艳露凝香,云雨巫山枉断肠
6 借问汉宫谁得似,可怜飞燕倚新妆
7 其三
8 名花倾国两相欢,长得君王带笑看
9 解释春风无限恨,沉香亭北倚阑干
$ nl 清平调.txt | sed '1,5a==============' # 在第1至5行,每行后面都新增内容
1 其一
==============
2 云想衣裳花想容,春风拂槛露华浓
==============
3 若非群玉山头见,会向瑶台月下逢
==============
4 其二
==============
5 一枝红艳露凝香,云雨巫山枉断肠
==============
6 借问汉宫谁得似,可怜飞燕倚新妆
7 其三
8 名花倾国两相欢,长得君王带笑看
9 解释春风无限恨,沉香亭北倚阑干
插入行
$ nl 清平调.txt | sed '1,3i==============' # 在1至3每行前面增加内容
==============
1 其一
==============
2 云想衣裳花想容,春风拂槛露华浓
==============
3 若非群玉山头见,会向瑶台月下逢
4 其二
5 一枝红艳露凝香,云雨巫山枉断肠
6 借问汉宫谁得似,可怜飞燕倚新妆
7 其三
8 名花倾国两相欢,长得君王带笑看
9 解释春风无限恨,沉香亭北倚阑干
替代行
$ nl 清平调.txt | sed '1,7c==============' # 替换1-7行内容
==============
8 名花倾国两相欢,长得君王带笑看
9 解释春风无限恨,沉香亭北倚阑干
替换是整体替换,而不是每一行替换
删除行
$ nl 清平调.txt | sed '1,7d' # 删除1至7行内容
8 名花倾国两相欢,长得君王带笑看
9 解释春风无限恨,沉香亭北倚阑干
删除空行
$ sed '/^$/d' 清平调.txt # 正则^$表示空行
在文件末尾追加内容
$ sed '$a 全诗构思精巧,辞藻艳丽\n描绘出人花交映、迷离恍惚的景象' 清平调.txt
其一
云想衣裳花想容,春风拂槛露华浓
若非群玉山头见,会向瑶台月下逢
其二
一枝红艳露凝香,云雨巫山枉断肠
借问汉宫谁得似,可怜飞燕倚新妆
其三
名花倾国两相欢,长得君王带笑看
解释春风无限恨,沉香亭北倚阑干
全诗构思精巧,辞藻艳丽
描绘出人花交映、迷离恍惚的景象
替换
$ sed 's/其/第/gi' 清平调.txt # g表示全局替换,如果没有g,只替换每行匹配到的第一个内容,i表示忽略大小写
第一
云想衣裳花想容,春风拂槛露华浓
若非群玉山头见,会向瑶台月下逢
第二
一枝红艳露凝香,云雨巫山枉断肠
借问汉宫谁得似,可怜飞燕倚新妆
第三
名花倾国两相欢,长得君王带笑看
解释春风无限恨,沉香亭北倚阑干
执行多个sed指令
$ nl 清平调.txt | sed -n -e '2,3p' -e '5,6p' # 获取不连续行
2 云想衣裳花想容,春风拂槛露华浓
3 若非群玉山头见,会向瑶台月下逢
5 一枝红艳露凝香,云雨巫山枉断肠
6 借问汉宫谁得似,可怜飞燕倚新妆
写入空行
$ sed 'G' 清平调.txt # 在每行之后新增一行
其一
云想衣裳花想容,春风拂槛露华浓
若非群玉山头见,会向瑶台月下逢
其二
一枝红艳露凝香,云雨巫山枉断肠
借问汉宫谁得似,可怜飞燕倚新妆
其三
名花倾国两相欢,长得君王带笑看
解释春风无限恨,沉香亭北倚阑干
$ sed 'G;G' 清平调.txt # 在每行之后新增两行
修改原文件
- 直接修改原文件
$ sed -i 's/其/第/g' 清平调.txt
- 拷贝原文件副本再进行修改
$ sed -i.bak 's/第/其/g' 清平调.txt # 先将内容复制一份 推荐如此使用,安全
$ ls | grep 清平调
清平调.txt
清平调.txt.bak
小括号反向引用
$ sed 's/\(其\)/\1中第/g' 清平调.txt
其中第一
云想衣裳花想容,春风拂槛露华浓
若非群玉山头见,会向瑶台月下逢
其中第二
一枝红艳露凝香,云雨巫山枉断肠
借问汉宫谁得似,可怜飞燕倚新妆
其中第三
名花倾国两相欢,长得君王带笑看
解释春风无限恨,沉香亭北倚阑干
仅当符合某条件时才进行内容替换
$ sed '/一/s/其/第/g' 清平调.txt # 当行中同时出现 一 与 其 时,才将 其 替换成 第
第一
云想衣裳花想容,春风拂槛露华浓
若非群玉山头见,会向瑶台月下逢
其二
一枝红艳露凝香,云雨巫山枉断肠
借问汉宫谁得似,可怜飞燕倚新妆
其三
名花倾国两相欢,长得君王带笑看
解释春风无限恨,沉香亭北倚阑干
批量替换
$ sed 's/其/第/g;s/一/1/g;s/二/2/g;s/三/3/g' 清平调.txt
第1
云想衣裳花想容,春风拂槛露华浓
若非群玉山头见,会向瑶台月下逢
第2
1枝红艳露凝香,云雨巫山枉断肠
借问汉宫谁得似,可怜飞燕倚新妆
第3
名花倾国两相欢,长得君王带笑看
解释春风无限恨,沉香亭北倚阑干
执行多个sed命令
-{}: 用;分开多个sed命令
nl /etc/passwd | sed '{20,30d;s/false/true/}' # 删除第20至30行,将false替换成true
读取一个输入 行
$ nl passwd | sed -n '{n;p}' # 间隔了一行取出 偶数行
$ nl passwd | sed -n '{p;n}' # 奇数行输出
# 另一种实现方式
$ nl passwd | sed '1~2p'
$ nl passwd | sed '2~2p'
$ nl passwd | sed -n '{n;n;p}'
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
6 sync:x:5:0:sync:/sbin:/bin/sync
9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
$ nl passwd | sed -n '{n;p;n}'
2 bin:x:1:1:bin:/bin:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
8 halt:x:7:0:halt:/sbin:/sbin/halt
替换固定字符串
$ sed 's/^[a-z_-]\+/& /' /etc/passwd # 用户名后加上空格
$ sed 's/^[a-z_-]\+/\U&/' /etc/passwd # 将用户名替换成大写
数据筛选
$ sed 's/\(^[a-z0-9_-]\+\):x:\([0-9]\+\):\([0-9]\+\):.*$/user:\1 uid:\
2 gid:\3/' /etc/passwd
user:root uid:0 gid:0
user:daemon uid:1 gid:1
user:bin uid:2 gid:2
...
复制指定文件插入到匹配行
$ echo -e '2412424124\n3432534\n5353523523' > 123.txt
$ echo -e 'dfgetetetete\njpkpwefwe\nlidwoew' > abc.txt
$ sed '1r 123.txt' abc.txt # 将123.txt插入到abc.txt的第1行后面
dfgetetetete
2412424124
3432534
5353523523
jpkpwefwe
lidwoew
读文件并不改变两个文件的内容,只是输出,需要用重定向将结果保存
提前退出
$ nl /etc/passwd | sed '3q' # 只取出前3行
1 root:x:0:0:root:/root:/bin/zsh
2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
3 bin:x:2:2:bin:/bin:/usr/sbin/nologin
$ nl /etc/passwd | sed '/nologin/q' # 找到第一个nologin就退出
1 root:x:0:0:root:/root:/bin/zsh
2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
与find结合使用
find ./ -type f -exec sed -i -e 's/charset=gbk/charset=utf-8/g' {} \; # 将find检索结果文件进行替换
网友评论