Linux 文本工具之 sed 命令的使用


分类: Linux
评论: 2

Linux 文本工具之 sed 命令的使用



分类: Linux
评论: 2

概述

sed 全称是 Stream EDitor,它是针对行的编辑器。

从文件或者管道读取一行,然后处理一行,接着又读取一行,处理一行,这样循环来回,知道所有行都处理完成。

sed 在处理行的时候,首先将当前需要处理的行读取到临时缓冲区,有个专业术语叫模式空间,

sed 所有处理工作都是针对缓存区这一文本行进行处理,并不是直接在源文件上面修改。对模式空间的文本行执行相关处理指令之后,默认的将缓冲区文本行进行输出到屏幕。

sed 处理方式是读取一行处理一行,所以在执行效率和空间效率上面有很大的优势,速度极快,不会出来卡顿现象。

像 vim 这类编辑器,就有可能出现卡顿现象,因为它的工作方式是直接将整个文件读取到内存。

如何使用?

命令语法

sed [OPTION]... {script-only-if-no-other-script} [input-file]...

命令选项

如果未给出 -e、-expression、-f 或 --file 选项,则第一个非选项参数作为 sed 脚本进行解释。

全部剩下的参数是输入文件的名称;如果未指定输入文件,则读取标准输入。

常用选项

 -n # 禁止自动打印
 -e # 多点编辑
 -E、-r # 扩展正则表达式
 -i.bak # 备份,并且修改源文件,若是不加后缀表示不备份
 -f file # 从文件中读取脚本

地址格式

'地址命令[;地址命令]......'

这里面包含两部分:地址、命令

支持地址

1. 不给地址:对全文进行处理
2. 单地址:
   #:指定的行
   $:最后一行
   /pattern/:被此处模式所能够匹配到的每一行
3. 地址范围:
   #,#     #从#行到第#行,3,6 从第3行到第6行
   #,+#   #从#行到+#行,3,+4 表示从3行到第7行
   /pat1/,/pat2/
   #,/pat/
4. 步进:~
     1~2 奇数行
     2~2 偶数行

支持命令

p # 打印当前模式空间内容,追加到默认输出之后
Ip # 忽略大小写输出
d # 删除模式空间匹配的行,并立即启用下一轮循环
a [\\]text # 在指定行后面追加文本,支持使用\n实现多行追加
i [\\]text # 在行前面插入文本
c [\\]text # 替换行为单行或多行文本
w /path/file #保存模式匹配的行至指定文件
r /path/file # 读取指定文件的文本至模式空间中匹配到的行后
= # 为模式空间中的行打印行号
! # 模式空间中匹配行取反处理
s/pattern/string/修饰符 # 查找替换,支持使用其它分隔符,可以是其它形式:s@@@,s###
替换修饰符:
g # 行内全局替换
p # 显示替换成功的行
w   /PATH/FILE # 将替换成功的行保存至文件中
I,i   # 忽略大小写
\ # 转义,针对在地址后面需要使用特殊字符时候,需要使用转义,否则无效

范例

# 显示某一行
cat /etc/passwd | sed -n '1p'
cat /etc/passwd | sed -n '2p'

# 查找替换,g 是全局替换
sed 's/root/abc/' /etc/passwd
sed 's/root/abc/g' /etc/passwd

# 显示空行的行号
sed -n '/^$/=' file

# 多点编辑
sed -n -e 's/root/abc/p' -e 's/^bin/sbin/gp' /etc/passwd

# 修改源文件,并且备份,指定后缀 .bak
sed -i.bak -n -e 's/root/abc/pg' -e 's/^bin/sbin/gp' /home/passwd

# 在偶数行前后插入,以及替换本行,插入插入多行使用 \n 表示换行,第一个 \ 表示后面的都是有效字符
seq 10 | sed '0~2a\after'
seq 10 | sed '0~2i\before'
seq 10 | sed '0~2c\current'

# 多个脚本,删除 2,4,6 三行
seq 10 | sed '2d;4d;6d'

# 对模式空间的行取反,! 取反之后必须要跟着处理命令
seq 10 | sed '0~2!p'

# 获取 ip 地址,使用正则分组的特性,可以轻松的对字符串进行分组
ifconfig | sed -nE '2s/[^0-9]+([0-9.]+).*/\1/p'
ifconfig | sed -nE '2s/[^0-9]+([0-9.]+).*/\2/p'

# 简单获取目录和基名,使用正则分组
pwd | sed -nE 's#(^/.*)/([^/]+/?)#\2#p'

# 适用多样性的目录结构,第一个获取目录,第二个获取基名
echo "/etc/fstab" | sed -nE 's#(^/.*)/+([^/]+)|(^/)([^/].*)|(^/$)#\1\3\5#p'
echo "/etc/fstab" | sed -nE 's#(^/.*)/+([^/]+)|(^/)([^/].*)|(^/$)#\2\4\5#p'

# 取消注释和加上注释 # 
sed -nE '/^#/s/^#//p' /etc/fstab
sed -nE '/^[^#]+/s/^/#/p' /etc/fstab

# 获取分区利用率
df | sed -nE '/^\//s# .* ([0-9]+)% .*# \1%#p'

# 修改网卡名称,从 0 开始,在 GRUB_CMDLINE_LINUX 一行最后增加一项 net.ifnames=0
sed -nE '/^GRUB_CMDLINE_LINUX/s#"$# test"#p' /etc/default/grub

# 删除注释和空行,查看有效配置
sed -E '/^([ \t\v]*#|$)/d' /apps/httpd/conf/httpd.conf

sed 允许使用变量替换,除了双引号包含变量会解析之外,还有三个单引号包含变量也会解析,例如:

TEST=test;sed -nE 's/root/'''$TEST'''/p' passwd
TEST=test;sed -nE "s/root/$TEST/p" passwd

高级特性

sed 中除了模式空间,还另外还支持保持空间(Hold Space),利用此空间,可以将模式空间中的数据,临时保存至保持空间,从而后续接着处理,实现更为强大的功能。

这意味者有两个空间可以存储当前处理的行,以及之前处理的结果。那么,我们就可以采用两个空间的数据相互交替,达到组装数据、过滤数据等效果。

常见的高级命令

P # 打印模式空间开端至\n内容,并追加到默认输出之前

h # 把模式空间中的内容覆盖至保持空间中

H # 把模式空间中的内容追加至保持空间中

g # 从保持空间取出数据覆盖至模式空间

G # 从保持空间取出内容追加至模式空间

x # 把模式空间中的内容与保持空间中的内容进行互换

n # 读取匹配到的行的下一行覆盖至模式空间

N # 读取匹配到的行的下一行追加至模式空间

d # 删除模式空间中的行

D # 如果模式空间包含换行符,则删除直到第一个换行符的模式空间中的文本,并不会读取新的输入行,而使用合成的模式空间重新启动循环。如果模式空间不包含换行符,则会像发出d命令那样启动正常的新循环

范例

# 打印偶数行
seq 10 | sed -n 'n;p

# 将文件倒叙显示,这里有三个脚本,每一行都处理一遍
# 1. 除了第一行之外,将保持空间的内容追加到模式空间
# 2. 将模式空间内容覆盖到保持空间
# 3. 除了最后一行,删除模式空间内容
sed '1!G;h;$!d' FILE

# 显示最后一行
sed ‘N;D’FILE

# 筛选只需要的行重新组装
seq 10 |sed  '3h;9G;9!d'

练习题

相关扩展