文本处理命令sed的详解

文本处理三剑客之sed

sed命令是我们学习linux文本处理命令中必不可少的命令,和awk,grep并称为三剑客。接下来来详细介绍下sed的用法,主要分为下面四个部分

  1. sed命令的工作原理
  2. sed的常用编辑命令
  3. sed的替换命令
  4. sed的特殊用法

一、sed命令的工作原理

sed是一种支持正则表达式的非交互式流编辑器(stream editor)。

所谓非交互式,是指使用sed只能在命令行下输入编辑命令来编辑文本,然后在屏幕上查看输出;而所谓流编辑器,是指sed每次只从文件(或输入)读入一行,然后对该行进行指定的处理,并将结果输出到屏幕(除非取消了屏幕输出又没有显式地使用打印命令),接着读入下一行。整个文件像流水一样被逐行处理然后逐行输出。

sed不是在原输入上直接进行处理的,而是先将读入的行放到缓冲区中,对缓冲区里的内容进行处理,处理完毕后也不会写回原文件(除非用shell的输出重定向来保存结果),而是直接输出到屏幕上。sed运行过程中维护着两个缓冲区,一个是活动的“模式空间(pattern space)”,另一个是起辅助作用的“暂存缓冲区(holding space)”。一般情况下,每当运行sed,sed首先把第一行装入模式空间,进行处理后输出到屏幕,然后将第二行装入模式空间替换掉模式空间里原来的内容,然后进行处理,以此类推。

一般情况下暂存缓冲区是用不到的,但有特殊的命令可以在模式空间与暂存缓冲区之间交换数据,后文将有介绍。由于sed对文本的所有操作都是在缓冲区里进行的,所以不会对原文件造成任何破坏。

sed的工作过程:
文本处理命令sed的详解_第1张图片

二、sed的常用编辑命令

接下来就介绍下sed的常用的用法:

sed的语法命令格式
sed [选项] sed编辑命令 输入文件
shell 命令 | sed [选项] sed编辑命令
sed [选项] -f sed脚本文件 输入文件

sed的常用选项
-n:只显示匹配处理的行(否则会输出所有)
-e:执行多个编辑命令时(一般用;代替)
-i:直接在文件中进行修改,而不是输出到屏幕
-r:支持扩展正则表达式
-f:从脚本文件中读取内容并执行(文件中的编辑命令每行一个,不用;隔开)

sed的常用编辑命令
p:打印匹配行 print
d:删除指定行 delete
a:在匹配行后面追加 append
i:在匹配行前面插入 insert
c:整行替换
r:将文件的内容读入 read
w:将文本写入文件 write
s:字符串替换(匹配正则表达式)substitution

sed的p命令示例
sed -n ‘行号1,行号2p’ 输入文件
sed -n ‘2,3p’ /etc/passwd 显示2到3行

[root@gushuai ~]# sed -n '2,3p' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin

sed -n ‘10p’ /etc/passwd 显示第10行

[root@gushuai ~]# sed -n '10p' /etc/passwd
operator:x:11:0:operator:/root:/sbin/nologin

sed -n ‘$p’ /etc/passwd 显示最后1行

[root@gushuai ~]# sed -n '$p' /etc/passwd
shuaigu:x:8917:8921::/home/shuaigu:/bin/bash

sed -n ‘2,+2p’ /etc/passwd 显示234行

[root@gushuai ~]# sed -n '2,+2p' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin

sed -n ‘3,100!p’ /etc/passwd 显示1到2行

[root@gushuai ~]#  sed -n '3,100!p' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin

; 表示执行多个命令
sed -n “1p;3p;5p” /etc/passwd 只是1,3,5行的内容

这样可以不连续地输出1,3,5行

[root@gushuai ~]# sed -n "1p;3p;5p" /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:2:2:daemon:/sbin:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

sed -n ‘/bash/p’ /etc/passwd
显示包含bash的行

[root@gushuai ~]# sed -n '/bash/p' /etc/passwd 
root:x:0:0:root:/root:/bin/bash
gushuai:x:1000:1000::/home/gushuai:/bin/bash
yalin:x:1021:1021::/home/yalin:/bin/bash
lele:x:1022:1022::/home/lele:/bin/bash
zhangyong:x:1023:1023::/home/zhangyong:/bin/bash
huangxinyi:x:1024:1024::/home/huangxinyi:/bin/bash
zhaiwenxiu:x:1025:1025::/home/zhaiwenxiu:/bin/bash
wangxin:x:2001:1026::/home/wangxin:/bin/bash
xieyuqi:x:1027:1027::/home/xieyuqi:/bin/bash
guzongping:x:1028:1028::/home/guzongping:/bin/bash
liushulan:x:1029:1029::/home/liushulan:/bin/bash
gushai:x:1030:1030::/home/gushai:/bin/bash
zhangjie:x:1031:1031::/home/zhangjie:/bin/bash
califeng:x:1032:1032::/home/califeng:/bin/bash
cali123:x:1033:1033::/home/cali123:/bin/bash
furong:x:1034:1034::/home/furong:/bin/bash
panjinhao:x:1035:1035::/home/panjinhao:/bin/bash

sed里单引号和双引号的区别:
双引号里可以使用shell里的变量
单引号不行
单引号和双引号里都可以存放模式

比如:

[root@gushuai ~]# a=5
[root@gushuai ~]# b=10
[root@gushuai ~]# cat -n /etc/passwd|sed -n "${a}p;${b}p"
     5	lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
    10	operator:x:11:0:operator:/root:/sbin/nologin

sed的d命令示例

删除操作可以根据行号和模式匹配进行操作

[root@gushuai ~]# cat -n /etc/fstab
     1	
     2	#
     3	# /etc/fstab
     4	# Created by anaconda on Wed Jun  3 20:21:49 2020
     5	#
     6	# Accessible filesystems, by reference, are maintained under '/dev/disk/'.
     7	# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info.
     8	#
     9	# After editing this file, run 'systemctl daemon-reload' to update systemd
    10	# units generated from this file.
    11	#
    12	/dev/mapper/cl-root     /                       xfs     defaults        0 0
    13	UUID=30184cc9-6264-43fb-8db4-a9b35dcf6439 /boot                   ext4    defaults        1 2
    14	/dev/mapper/cl-home     /home                   xfs     defaults        0 0
    15	/dev/mapper/cl-swap     swap                    swap    defaults        0 0

cat -n /etc/fstab|sed ‘3,5d’
删除3到5行

[root@gushuai ~]# cat -n /etc/fstab|sed  '3,5d' 
     1	
     2	#
     6	# Accessible filesystems, by reference, are maintained under '/dev/disk/'.
     7	# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info.
     8	#
     9	# After editing this file, run 'systemctl daemon-reload' to update systemd
    10	# units generated from this file.
    11	#
    12	/dev/mapper/cl-root     /                       xfs     defaults        0 0
    13	UUID=30184cc9-6264-43fb-8db4-a9b35dcf6439 /boot                   ext4    defaults        1 2
    14	/dev/mapper/cl-home     /home                   xfs     defaults        0 0
    15	/dev/mapper/cl-swap     swap                    swap    defaults        0 0

图中可以看出确实是删除了三到五行。

sed的a命令示例
追加操作可以根据行号和模式匹配进行操作
cat /etc/fstab|sed ‘1a 1111111111111111’
在第一行后面追加后面的字符串
sed ‘/boot/a 1111111111111’ /etc/fstab
在包含boot的行下面追加后面的字符串

这里比较好理解,就不贴图了。

sed的i命令示例
同样的和a命令差不多,就不多赘述了。

插入操作可以根据行号和模式匹配进行操作
sed ‘$i 1111111111111111’ /etc/fstab
在最后一行前面插入后面的字符串
sed ‘/defaults/i 1111111111111’ /etc/fstab
在包含defaults的行前面插入后面的字符串

sed的c命令示例
c命令也用的不多,会用一点就可以了。
更改整行操作可以根据行号和模式匹配进行操作

sed ‘/id:/c id:5:initdefault:’ /etc/inittab
将id:所在的行整行替换成后面的字符串
sed ‘3c ONBOOT=no’ ifcfg-eth0
将第三行改成后面的字符串

sed的r命令示例
读入操作可以根据行号和模式匹配进行操作

sed ‘$r /etc/hosts’ /etc/fstab
在fstab文件的末尾后面读入hosts文件的内容
df -h | sed '/dev/sda1/r /etc/mtab‘
在/dev/sda1后面读入mtab文件的内容

sed的w命令示例
写入文件操作可以根据行号和模式匹配进行操作

sed ‘1w abc.txt’ /etc/passwd
将文件的第一行写入abc.txt
sed ‘/^#/!w abc.txt’ /etc/inittab
将所有不是#开头的行都写入abc.txt
sed -r ‘/#|$/!w abc.txt’ /etc/vsftpd/vsftpd.conf
将配置文件中除了空行和注释都写入abc.txt

三、sed的替换命令

sed中的替换是由s命令来实现的,下面就来看看sed中的替换是怎么替换的吧。

sed的s命令语法格式
sed -n [行号或模式]s/查找内容/替换内容/[替换标记] 文件
替换操作可以根据行号和模式匹配进行操作

替换标记有四种
数字:替换每行的第几个
g:全局替换,否则只替换第一个字符串。例如ng从第n个开始替换
p:显示被执行替换操作的行和-n合用
w:将执行替换操作的行输出到指定文件

sed的s命令
sed -n ‘s/root/ROOT/2p’ /etc/passwd
将文件中每行的第2个root替换为ROOT
sed ‘/^id/s/:3:/:5:/’ /etc/inittab
将文件中找到以id开头的行中的:3:替换成:5:
sed ‘/^local_enable/s/YES/NO/’ vsftpd.conf
禁止本地用户登陆
sed ‘s/bash/nologin/ ; s/sbin/bin/’ /etc/passwd
将文件中bash替换成nologin,同时将sbin替换成bin

sed -n ‘2,10s/^/#/p’ /etc/passwd
在2到10行前面加上注释
sed -n ‘s/$/?/p’ /etc/passwd
在每行末尾加上?

sed的命令中&的用法
&用于表示替换命令中的匹配模式

[root@gushuai ~]# echo 'I have a fat cat'|sed 's/.at/".at"/g'
I have a ".at" ".at"
[root@gushuai ~]# echo 'I have a fat cat'|sed 's/.at/"&"/g'
I have a "fat" "cat"

sed -rn ‘s/<[0-9]{3}>/&0/gp’ /etc/passwd
将所有三位数字后面加个0

sed的命令中标签的用法
标签:sed使用圆括号定义替换模式中的部分字符
标签可以方便在后面引用,每行指令最多使用9个标签

sed -r ‘s/([a-Z]+)(.*)/\1/’ /etc/passwd
显示文件的第一列

[root@gushuai ~]# sed -rn 's/([a-Z]+)(.*)/\1/p' /etc/passwd
root
bin
daemon
adm
lp
sync
shutdown
halt
mail
operator
games
ftp
nobody
dbus
systemd
systemd
tss
polkitd
unbound
sssd
sshd

将原本要输出的aaa bbb ccc输出成ccc bbb aaa

[root@gushuai ~]# echo aaa bbb ccc | sed -r 's/([a-z]+) ([a-z]+) ([a-z]+)/\3 \2 \1/'
ccc bbb aaa

四、sed命令的特殊用法

模式空间(pattern space)和暂存空间(holding space)相关的命令:

n 输出模式空间行,读取下一行替换当前模式空间的行,执行下一条处理命令而非第一条命令。
N 读入下一行,追加到模式空间行后面,此时模式空间有两行。
h 把模式空间里的行拷贝到暂存空间。
H 把模式空间里的行追加到暂存空间。
g 用暂存空间的内容替换模式空间的行。
G 把暂存空间的内容追加到模式空间的行后。
x 将暂存空间的内容于模式空间里的当前行互换。
! 对所选行以外的所有行应用命令。

下面以一个例子来说明上面命令的用法,例如有一个文件,我们可以用tac命令反序打印出文件的内容,其实用sed的话也可以实现,这里先将结果列出,再详细讲解。

[root@gushuai ~]# cat file.txt 
First
Second
three
[root@gushuai ~]# sed '1!G;h;$!d' file.txt
three
Second
First

一行命令就可实现。

通过下面的讲解大家可以了解到sed的处理机制以及处理过程:

说明:

第一行左边为文件内容,箭头所指为sed当前处理的行,右侧为sed命令;
后面三行左侧绿色为模式空间内容,右侧蓝色为保持空间内容。
每次sed只读取文件中一行到模式空间,即每次执行sed命令前,模式空间中只有文件中当前处理行内容,这一点没有在图中表现。
每一行表示一个命令处理完后两个空间中的内容
困为每一步骤都很清楚,所以只把执行的结果以图形表示,不做说明,可以对照前面对sed命令的说明,以加深理解

1,读取文件的行一行"First"进行处理,最后一个命令将模式空间内容删除,所以不会在屏幕上打印内容
文本处理命令sed的详解_第2张图片
2,读取第二行“Sencond”进行处理,最后一个命令将模式空间内容删除,所以不会在屏幕上打印内容
文本处理命令sed的详解_第3张图片
3,读取第三行“three”进行处理,注意sed处理完之后会把,会把模式空间中内容打印到屏幕并自动清空模式空间(这个没在图中表现)
文本处理命令sed的详解_第4张图片
以上就是sed命令的用法了,本人刚开始写博客没多久,有写的不好的地方大家可以指正出来,我会改进的,希望大家看到这篇文章可以对sed有更深的理解。

你可能感兴趣的:(linux,linux)