导语
Linux的文本处理三剑客:
grep,egrep,fgrep : 文本过滤器;
sed : Stream EDitor , 流编辑器,对文本内容逐行操作;
awk : 文本格式化工具,报告生成器;
sed工作机制和特性:
1> sed是一个行编辑器,能同时处理多个文件;
2> 默认不直接编辑源文件,而是以行为单位复制到内存执行编译操作;
3> sed读取文件时,一次读取一行内容,把读取的内容放置在sed自己的工作空间进行编辑操作;
4> sed的工作空间叫模式空间(pattern space);在模式空间对文本进行操作,执行结果输出至标准输出(stdout);
5> sed进行文本过滤时,可以采用正则表达式来匹配模式;被模式匹配到的行经过编辑后输出至标准输出,没有被模式匹配到的行默认直接输出至标准输出,也可以隐藏此标准输出;
6> sed对匹配到的行内容进行编辑操作后,可以保存至另一个内存空间,此空间叫保持空间(hold space);
7> pattern space 和 hold space 的数据可做魔术式的数据交互处理;
图解sed工作机制:
1> 逐行读取文件内容,每读取一行内容就放入’pattern space’中进行模式匹配;
2> 在’pattern space’中读入的行内容根据模式进行匹配,然后再根据指定的编辑命令做出相关动作:删除、打印、替换等;
3> 未被模式匹配到的行默认动作是输出至标准输出;
4> 文件的每行内容以逐行方式读入’pattern space’中,文件所有内容只能被读取一次;
5> ‘hold space’中默认是没有任何数据的;
6> ‘pattern space’与’hold space’之间可进行数据交互:覆盖、追加;
sed命令:
sed – stream editor for filtering and transforming text. 用于过滤和转换文本的流编辑器;
sed命令使用格式:
sed [OPTION]… {script-only-if-no-other-script} [input-file]…
1、 OPTIONS:
-n, –quiet, –silent : 不输出模式空间的内容至屏幕;只显示被模式匹配到的行,未被模式匹配到的行则不显示(‘p’,’d’编辑命令比较特殊,除外);
-e script, –expression=script : 可以指定多个编辑脚本,实现多点编辑;一个’-e’选项指定一个模式;
-f script-file, –file=script-file : 指定sed脚本,脚本内容为每行一个编辑命令;
-r, –regexp-extended : 支持扩展正则表达式;
-i[SUFFIX], –in-place[=SUFFIX] : 直接编辑源文件;
NOTE: 多个选项组合使用时候,’-n’,’-r’ 要放置在’-e’前面;
2、 script-only-if-no-other-script : 地址定界编辑命令(由2部分组成);
2.1 地址定界:
1> 空地址: 表示对全文进行编辑处理;
2> 单地址形式:
# : 表示指定行;
/pattern/ : 表示被此模式所匹配到的每一行;
3> 地址范围:
$ : 表示最后一行;
#,# : 准确数字,从第几行到第几行;
#,+# : 从第几行开始,后面加多少行;
#,/pattern/ : 表示从第几行开始,到第一次被模式匹配到的行;
/pattern1/,/pattern2/ : 表示第一次被模式1匹配到的行,至第一次被模式2匹配到的行;
4> 步进: 用符号表示,~ ;
1~2 : 表示从1开始,步进长度为2,即所有奇数;
2~2 : 表示从2开始,步进长度为2,即所有偶数;
2.2 编辑命令
d : 删除
p : 小写字母’p’,显示模式空间中的内容;
i \text : 在行前面插入指定的文本内容’text’,支持使用’\n’,可实现多行插入;
a \text : 在行后面插入指定的文本内容’text’,支持使用’\n’,可实现多行插入;
c \text : 对匹配到的行(整行内容)替换为指定的文本内容’text’,替换内容后,支持使用’\n’,可实现多行插入;
w /PATH/TO/SOMEFILE : 保存模式空间中匹配到的行至指定的文件中;
r /PATH/FROM/SOMEFILE : 读取另一个文件的内容到当前文件被模式匹配到的行后面;可实现文件合并操作;
= : 在被模式匹配到的行的上方(匹配到的行的上面新开一行)打印显示行号;
! : 条件取反,’!’感叹号放在模式与命令之间,中间无空格;是命令取反,而不是模式取反;
s/// : 查找替换操作;其分隔符可自行指定,常用的分隔符有’/’,’@’,’#’等;具体应用有如下;
s///g : 全局替换,默认显示替换后的内容以及未被模式匹配的内容;
s///gw /PATH/TO/SOMEFILE : 全局查找替换后,替换后的行内容保存至另一个文件,同时默认打印出’替换后的内容以及未被模式匹配的内容’;
s///gp : 全局替换,打印出双份替换后的内容、未被模式匹配到的行内容;
2.3 高级编辑命令
h : 把’pattern space’中的内容覆盖至’hold space’;
H : 把’pattern space’中的内容追加至’hold space’;
g : 把’hold space’中的内容覆盖至’pattern space’;
G : 把’hold space’中的内容追加至’pattern space’;
x : 小写字母’x’,把’pattern space’中的内容与’hold space’空间中的内容互换;
n : 把匹配到的行的下一行覆盖读入’pattern space’中;
N : 把匹配到的行的下一行追加读入’pattern space’中;
d : 删除’pattern space’中的行;
D : 删除多行’pattern space’中的所有行;
==================================================================
==================================================================
第一部分:基本编辑命令的使用 ============================== ~]# sed '1~2d' /etc/fstab 删除奇数行,只显示偶数行; ~]# sed -n '1~2d' /etc/fstab 删除奇数行,不显示偶数行; ~]# sed '1~2p' /etc/fstab 匹配奇数行,奇数行会显示;偶数行未被匹配到,但默认也会输出显示;所以:奇数行会显示2遍; ~]# sed -n '1~2p' /etc/fstab 匹配奇数行,显示奇数行;'-n' 选项的作用是:不显示未被模式匹配到的行,此处为不显示偶数行; ~]# sed '/^#/d' /etc/fstab 删除'#'号开头的行; ~]# sed '/^[^#]/w /tmp/fstab.new' /etc/fstab 把非'#'号开头的行复制到另一个文件; ~]# sed '/^#/!w /tmp/fstab.new' /etc/fstab 从第3行开始,奇数行的上方新开一行打印行号; --------------------------------------- [root@kouyuushinn ~]# [root@kouyuushinn ~]# sed '3~2=' /etc/fstab # 3 # /etc/fstab # Created by anaconda on Wed Dec 27 05:42:43 2017 5 # # 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 # 9 /dev/mapper/centos-root / xfs defaults 0 0 UUID=78fbb254-bb6a-4847-8890-4410ccb77410 /boot xfs defaults 0 0 11 /dev/mapper/centos-swap swap swap defaults 0 0 13 /dev/sdb1 /sdb1 xfs defaults 0 0 UUID=6573bffb-af78-4ea2-b4d1-d2303cab8cad /sdb2 ext4 defaults 0 0 15 UUID=05594ee4-41bd-4c37-b826-650b1f49ad64 /sdb5 xfs defaults 0 0 /dev/sdb6 /sdb6 ext4 defaults 0 0 17 UUID=e8c1aa0f-b241-422c-b05a-a4e34e14672d /mydata ext4 defaults 0 0 UUID=a2180257-513b-4285-92aa-003ed62e2eda /lvdata btrfs defaults 0 0 [root@kouyuushinn ~]# [root@kouyuushinn ~]# 在'UUID'字符串所在行的上方打印行号; ------------------------------------ [root@kouyuushinn ~]# sed '/^UUID/=' /etc/fstab # # /etc/fstab # Created by anaconda on Wed Dec 27 05:42:43 2017 # # Accessible filesystems, by reference, are maintained under '/dev/disk' # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info # /dev/mapper/centos-root / xfs defaults 0 0 10 UUID=78fbb254-bb6a-4847-8890-4410ccb77410 /boot xfs defaults 0 0 /dev/mapper/centos-swap swap swap defaults 0 0 /dev/sdb1 /sdb1 xfs defaults 0 0 14 UUID=6573bffb-af78-4ea2-b4d1-d2303cab8cad /sdb2 ext4 defaults 0 0 15 UUID=05594ee4-41bd-4c37-b826-650b1f49ad64 /sdb5 xfs defaults 0 0 /dev/sdb6 /sdb6 ext4 defaults 0 0 17 UUID=e8c1aa0f-b241-422c-b05a-a4e34e14672d /mydata ext4 defaults 0 0 18 UUID=a2180257-513b-4285-92aa-003ed62e2eda /lvdata btrfs defaults 0 0 [root@kouyuushinn ~]# ~]# sed '/^#/d' /etc/fstab 删除'#'开头的行,显示非'#'开头的行; ~]# sed '/^#/!d' /etc/fstab 不删除'#'开头的行,显示'#'开头的行; 删除/etc/fstab文件中所有以空白字符开头的行的行首的所有空白字符; ~]# sed 's/^[[:space:]]\+//gw /tmp/fstab.11' /etc/fstab ~]# sed 's@^[[:space:]]\+@@gw /tmp/fstab.11' /etc/fstab 删除/etc/fstab文件中所有以#开头的行的行首的#号及#号后面的所有空白字符; ~]# sed 's@^#[[:space:]]*@@gw /tmp/fstab.22' /etc/fstab 删除/etc/fstab文件中所有以#开头的行的行首的#号及#号后面的所有空白字符,以及删除以UUID开头的行; ~]# sed -e 's@^#[[:space:]]\+@@g' -e '/^UUID/d' /etc/fstab 删除/etc/fstab文件中所有以#开头的行的行首的#号及#号后面的所有空白字符,以及删除非UUID开头的行; ~]# sed -e 's@^#[[:space:]]\+@@g' -e '/^[^UUID]/d' /etc/fstab ~]# sed -e 's@^#[[:space:]]\+@@g' -e '/^UUID/!d' /etc/fstab -------------------------------------------------------------- ~]# sed -r -e 's@^#[[:space:]]+@@g' -e '/^UUID/!d' /etc/fstab ~]# sed -r -n -e 's@^#[[:space:]]+@@g' -e '/^UUID/!d' /etc/fstab 选项'-r''-n'在'-e'前面;'-r''-n'顺序可调换; 取出给定路径的'路径名'和'基名': ------------------------------- [root@kouyuushinn ~]# [root@kouyuushinn ~]# dirname /etc/sysconfig/network-scripts/ /etc/sysconfig [root@kouyuushinn ~]# [root@kouyuushinn ~]# dirname /etc/sysconfig/network-scripts/ifcfg-ens33 /etc/sysconfig/network-scripts [root@kouyuushinn ~]# [root@kouyuushinn ~]# echo "/etc/sysconfig/network-scripts/" | sed 's@[^/]\+/\?$@@' | sed 's@/$@@' /etc/sysconfig [root@kouyuushinn ~]# [root@kouyuushinn ~]# echo "/etc/sysconfig/network-scripts/ifcfg-ens33" | sed 's@[^/]\+/\?$@@' | sed 's@/$@@' /etc/sysconfig/network-scripts [root@kouyuushinn ~]# [root@kouyuushinn ~]# [root@kouyuushinn ~]# basename /etc/sysconfig/network-scripts/ network-scripts [root@kouyuushinn ~]# [root@kouyuushinn ~]# [root@kouyuushinn ~]# basename /etc/sysconfig/network-scripts/ifcfg-ens33 ifcfg-ens33 [root@kouyuushinn ~]# [root@kouyuushinn ~]# [root@kouyuushinn ~]# echo /etc/sysconfig/network-scripts/ | egrep -o "[^/]+/?$" | cut -d "/" -f1 network-scripts [root@kouyuushinn ~]# [root@kouyuushinn ~]# echo /etc/sysconfig/network-scripts/ifcfg-ens33 | egrep -o "[^/]+/?$" ifcfg-ens33 [root@kouyuushinn ~]# [root@kouyuushinn ~]# 第二部分:高级编辑命令的理解 =============================== [root@kouyuushinn etc]# [root@kouyuushinn etc]# cat -n /etc/fstab 1 2 # 3 # /etc/fstab 4 # Created by anaconda on Wed Dec 27 05:42:43 2017 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 /dev/mapper/centos-root / xfs defaults 0 0 10 UUID=78fbb254-bb6a-4847-8890-4410ccb77410 /boot xfs defaults 0 0 11 /dev/mapper/centos-swap swap swap defaults 0 0 12 13 /dev/sdb1 /sdb1 xfs defaults 0 0 14 UUID=6573bffb-af78-4ea2-b4d1-d2303cab8cad /sdb2 ext4 defaults 0 0 15 UUID=05594ee4-41bd-4c37-b826-650b1f49ad64 /sdb5 xfs defaults 0 0 16 /dev/sdb6 /sdb6 ext4 defaults 0 0 17 UUID=e8c1aa0f-b241-422c-b05a-a4e34e14672d /mydata ext4 defaults 0 0 18 UUID=a2180257-513b-4285-92aa-003ed62e2eda /lvdata btrfs defaults 0 0 [root@kouyuushinn etc]# [root@kouyuushinn etc]# sed -n 'n;p' /etc/fstab # # Created by anaconda on Wed Dec 27 05:42:43 2017 # Accessible filesystems, by reference, are maintained under '/dev/disk' # UUID=78fbb254-bb6a-4847-8890-4410ccb77410 /boot xfs defaults 0 0 UUID=6573bffb-af78-4ea2-b4d1-d2303cab8cad /sdb2 ext4 defaults 0 0 /dev/sdb6 /sdb6 ext4 defaults 0 0 UUID=a2180257-513b-4285-92aa-003ed62e2eda /lvdata btrfs defaults 0 0 [root@kouyuushinn etc]# ~]# sed -n 'n;p' FILENAME 显示偶数行; 分析: 模式没有指定地址空间,所以逐行读取文件; 读取第1行到模式空间,根据'n'编辑命令,读取第2行覆盖至模式空间,第2行被模式匹配,并做打印输出(标准输出); 读取第3行到模式空间,根据'n'编辑命令,读取第4行覆盖至模式空间,第4行被模式匹配,并做打印输出(标准输出); 读取第5行到模式空间,根据'n'编辑命令,读取第6行覆盖至模式空间,第4行被模式匹配,并做打印输出(标准输出); ... 注意: 上面的信息中,虽然读入第4行内容到模式空间后进行了覆盖操作,但之前的被模式匹配到的第2行已经做了打印输出动作,所以不影响最终的显示结果; 从上面的分析中可看出,被匹配到的都是偶数行,模式匹配后的动作是标准输出; 选项'-n'的作用是未被模式匹配到的奇数行不做打印输出(静默模式);也就是说,'-n'的作用对象是未被模式匹配到的行; ======================================================== || 重点: !!! 逐行读取,逐行匹配,逐行编辑 !!! || ======================================================== ~]# sed 'n;d' FILENAME 显示奇数行; ~]# sed '1!G;h;$!d' FILENAME 逆序显示文件内容; ~]# sed '$!d' FILENAME 取出文件最后一行; ~]# sed '$!N;$!D' FILENAME 取出文件最后两行; ~]# sed '/^$/d;G' FILENAME 删除文件原有的所有空白行,而后为所有的非空白行下面添加一个空白行; ~]# sed 'G' FILENAME 在原有的每行下面添加一个空白行;