资讯专栏INFORMATION COLUMN

linux基础命令介绍十:文本流编辑 sed

flybywind / 2870人阅读

摘要:与不同,是一种非交互式的文本编辑器,同时它又是面向字符流的,每行数据经过处理后输出。只有被命令作用的字符串才会被输出。表示从中读取命令表示原地修改。表示如果替换成功,则输出模式空间内容至文件中。和表示匹配时不区分大小写。

vim不同,sed是一种非交互式的文本编辑器,同时它又是面向字符流的,每行数据经过sed处理后输出。

sed [OPTION]... [script] [file]...

sed的工作过程是这样的:首先,初始化两个数据缓冲区模式空间保持空间sed读取一行输入(来自标准输入或文件),去掉结尾的换行符( )后置于模式空间中,然后针对模式空间中的字符串开始执行‘sed命令’,每个命令都可以有地址与之相关联,地址可以看成是条件,只有在条件成立时,相关的命令才被执行;所有可执行命令都处理完毕后,仍处于模式空间中的字符串会被追加一个换行符后打印输出;之后读取下一行输入做同样的处理,直到主动退出(q)或输入结束。

地址

地址可以是如下的形式

1、number 表示行号
2、first~step 表示从first(数字)行开始,每隔step(数字)行
3、$ 表示最后一行(注意当出现在正则表达式中时表示行尾)
4、/regexp/ 表示匹配正则表达式regexp(关于正则表达式,请参见这一篇)
5、\%regexp% 表示匹配正则表达式regexp,%可以换成任意其他单个字符。(用于regexp包含斜线/的情况)
6、/regexp/I 匹配正则表达式regexp时不区分大小写
7、/regexp/M 启用正则多行模式,使$不止匹配行尾,还匹配 或 之前的位置;使^不止匹配行首,还匹配 或 之后的位置。此时可以用(`)匹配模式空间的开头位置,用(")匹配模式空间的结束位置。

还可以用逗号,分隔两个地址来表示一个范围

表示从匹配第一个地址开始,直到匹配第二个地址或文件结尾为止。如果第二个地址是个正则表达式,则不会对第一个地址匹配行进行第二个地址的匹配;如果第二个地址是行号,但小于或等于第一个地址匹配行行号,则只会匹配一行(第一个地址匹配行)。

8、0,/regexp/ 这种情况下,正则表达式regexp会在第一行就开始进行匹配。只有第二个地址是正则表达式时,第一个地址才能用0。
9、addr1,+n表示匹配地址addr1和其后的n行。
10、addr1,~n表示从匹配地址addr1开始,直到n的倍数行为止。
如果没有给出地址,所有的行都会匹配;在地址或地址范围后追加字符!表示对地址取反,所有不匹配的行才会被处理。

选项

-n 默认时每一行处理过的字符串都会被打印输出,此选项表示关闭此默认行为。只有被命令p作用的字符串才会被输出。
-f file表示从file中读取sed命令
-i 表示原地修改。应用此选项时,sed会创建一个临时文件,并将处理结果输出到此文件,处理完毕后,会将此临时文件覆盖至原文件。
-r 表示使用扩展的正则表达式

命令

p表示打印模式空间内容,通常配合选项-n一起使用

[root@centos7 ~]# seq 5
1
2
3
4
5
[root@centos7 ~]# 只输出第二行到第四行
[root@centos7 ~]# seq 5|sed -n "2,4p"
2
3
4
[root@centos7 ~]# 

d 删除模式空间内容,立即处理下一行输入。

#删除最后一行
[root@centos7 ~]# seq 5|sed "$d"
1
2
3
4
[root@centos7 ~]#

q 立即退出,不再处理任何命令和输入(只接受单个地址)

[root@centos7 ~]# seq 5|sed "/3/q"
1
2
3
[root@centos7 ~]#

n 如果没有使用选项-n,输出模式空间中内容后,读取下一行输入并覆盖当前模式空间内容。如果没有更多的输入行,sed会退出执行。

[root@centos7 ~]# seq 9|sed -n "n;p"
2
4
6
8
[root@centos7 ~]# 注意多个命令用分号分隔

s/regexp/replacement/flag 表示用replacement替换模式空间中匹配正则表达式regexp的部分。在这里符号/可以换成任意单个字符。

[root@centos7 ~]# echo "hello123world"|sed "s/[0-9]+/,/"  
hello,world
#注意这里+需要转义,如果使用选项-r则无需转义

在replacement中

1、 (n为1-9中的一个数字)表示对正则表达式中分组(...)的引用;

[root@centos7 ~]# echo "hello123world"|sed -r "s/[a-z]+([0-9]+)[a-z]+/1/"
123
[root@centos7 ~]# echo "hello123world"|sed -r "s/([a-z]+)[0-9]+([a-z]+)/1,2/"
hello,world

2、&表示模式空间中所有匹配regexp的部分;

[root@centos7 ~]# echo "hello123world"|sed -r "s/[0-9]+/:&:/"
hello:123:world

3、L 将后面的字符转化成小写直到 U 或 E 出现;
4、l 将下一个字符转化为小写;
5、U 将后面的字符转化成大写直到 L 或 E 出现;
6、u 将下一个字符转化为大写;
7、E 停止由 L 或 U 起始的大小写转化;

[root@centos7 ~]# echo "hello123world"|sed -r "s/^([a-z]+)[0-9]+([a-z]+)$/U1E,u2/"
HELLO,World
[root@centos7 ~]# 

flag

1、n数字n表示替换第n个匹配项

[root@centos7 ~]# head -1 /etc/passwd
root:x:0:0:root:/root:/bin/bash
#替换冒号分隔的第五部分为空
[root@centos7 ~]# head -1 /etc/passwd|sed "s/[^:]+://5"
root:x:0:0:/root:/bin/bash

2、g表示全局替换

[root@centos7 ~]# echo "hello123world"|sed "s/./U&E/"
Hello123world
[root@centos7 ~]# 
[root@centos7 ~]# echo "hello123world"|sed "s/./U&E/g"
HELLO123WORLD
[root@centos7 ~]#
#当数字n和g同时使用时,表示从第n个匹配项开始替换一直到最后匹配项
[root@centos7 ~]# head -1 /etc/passwd|sed "s/[^:]+://4g"
root:x:0:/bin/bash/

3、p表示如果替换成功,则打印模式空间内容。
4、w file表示如果替换成功,则输出模式空间内容至文件file中。
5、Ii表示匹配regexp时不区分大小写。

[root@centos7 ~]# echo "HELLO123world"|sed -r "s/[a-z]+//Ig"
123
[root@centos7 ~]#

6、Mm表示启用正则多行模式(如前所述)。(讲命令N时再举例)

y/source-chars/dest-chars/把source-chars中的字符替换为dest-chars中对应位置的字符,/可以换为其他任意单个字符,source-chars和dest-chars中字符数量必须一致且不能用正则表达式。

[root@centos7 ~]# echo hello|sed "y/el/LE/"      
hLEEo
[root@centos7 ~]#

a text表示输出模式空间内容后追加输出text内容

[root@centos7 ~]# seq 3|sed "1,2a hello" 
1
hello
2
hello
3
[root@centos7 ~]#

i text表示输出模式空间内容之前,先输出text内容

[root@centos7 ~]# seq 3|sed "$ihello"
1
2
hello
3
[root@centos7 ~]# 

c text表示删除匹配地址或地址范围的模式空间内容,输出text内容。如果是单地址,则每个匹配行都输出,如果是地址范围,则只输出一次。

[root@centos7 ~]# seq 5|sed "1,3chello"
hello
4
5
[root@centos7 ~]# seq 5|sed "/^[^3-4]/c hello" 
hello
hello
3
4
hello

=表示打印当前输入行行号

[root@centos7 ~]# seq 100|sed -n "$="
100
[root@centos7 ~]# seq 100|sed -n "/^10|^20/="
10
20
100
[root@centos7 ~]# 转义的|表示逻辑或

r file表示读取file的内容,并在当前模式空间内容输出之后输出

[root@centos7 ~]# cat file 
hello world
[root@centos7 ~]# seq 3|sed "1,2r file"
1
hello world
2
hello world
3
[root@centos7 ~]# 

w file表示输出模式空间内容至file中

N读入一行内容至模式空间后,再追加下一行内容至模式空间(此时模式空间中内容形如 line1 line2 ),如果不存在下一行,sed会退出。

[root@centos7 ~]# seq 10|sed -n "N;s/
/ /p"
1 2
3 4
5 6
7 8
9 10
[root@centos7 ~]#
#s命令的m flag举例
[root@centos7 ~]# seq 3|sed "N;s/^2/xxx/" 
1
2
3
[root@centos7 ~]# seq 3|sed "N;s/^2/xxx/m"    
1
xxx
3
[root@centos7 ~]# seq 3|sed "N;s/1$/xxx/" 
1
2
3
[root@centos7 ~]# seq 3|sed "N;s/1$/xxx/M"
xxx
2
3

D如果模式空间中没有新行(如命令N产生的新行),则和命令d起同样作用;如果包含新行,则会删除第一行内容,然后对模式空间中剩余内容重新开始一轮处理。(注意:D后面的命令将会被忽略)

[root@centos7 ~]# seq 5|sed "N;D"  
5
[root@centos7 ~]# seq 5|sed "N;N;D"   
3
4
5

P打印模式空间中第一行内容

[root@centos7 ~]# seq 10|sed -n "N;P" 
1
3
5
7
9
[root@centos7 ~]# seq 10|sed -n "N;N;P"
1
4
7
#注意另一种写法输出中的不同
[root@centos7 ~]# seq 10|sed -n "1~3P" 
1
4
7
10

g用保持空间中的内容替换模式空间中的内容

[root@centos7 ~]# seq 5|sed -n "g;N;s/
/xx/p"
xx2
xx4
[root@centos7 ~]# 

G追加一个换行符到模式空间,然后再将保持空间中的内容追加至换行符之后。(此时模式空间中内容形如 PATTERN HOLD )

[root@centos7 ~]# seq 5|sed "G;s/
/xx/"  
1xx
2xx
3xx
4xx
5xx

h用模式空间中的内容替换保持空间中的内容(注意此时模式空间中的内容并没有被清除)

[root@centos7 ~]# seq 5|sed -n "h;G;s/
/xx/p"
1xx1
2xx2
3xx3
4xx4
5xx5
[root@centos7 ~]# seq 5|sed -n "h;G;G;s/
/xx/gp"
1xx1xx1
2xx2xx2
3xx3xx3
4xx4xx4
5xx5xx5

H追加一个换行符到保持空间,然后再将模式空间中的内容追加至换行符之后。(此时保持空间中内容形如 HOLD PATTERN )

[root@centos7 ~]# seq 3|sed -n "H;G;s/
/xx/gp"
1xxxx1
2xxxx1xx2
3xxxx1xx2xx3
[root@centos7 ~]# 

x交换模式空间和保持空间的内容

[root@centos7 ~]# seq 9|sed -n "1!{x;N};s/
//p"
3
25
47
69
#处于{...}之中的是命令组

: label为分支命令指定标签位置(不允许地址匹配)

b label无条件跳转到label分支,如果省略了label,则跳转到整条命令结尾(即开始下一次读入)

#如删除xml文件中注释部分(之间的部分是注释,可以多行)
sed "//!{N;ba};d}" server.xml
#表示匹配之前一直执行N,匹配到-->之后删除模式空间中内容
#如在nagios的配置文件中,有许多define host{...}的字段,如下所示:
define host{
use windows-server
host_name serverA
hostgroups 060202
alias 060202
contact_groups yu
address 192.168.1.1
}
#现在需要删除ip地址是192.168.1.1的段,可以这样:
sed -i "/define host/{:a;N;/}/!ba;/192.168.1.1/d}" file
#注意和前一个例子中的区别

t label在一次输入后有成功执行的s替换命令才跳转到label,如果省略了label,则跳转到整条命令结尾(即开始下一次读入)

#如行列转换
[root@centos7 ~]# seq 10|sed ":a;$!N;s/
/,/;ta"
1,2,3,4,5,6,7,8,9,10
[root@centos7 ~]#
#如将MAC地址78A35114F798改成带冒号的格式78:A3:51:14:F7:98
[root@centos7 temp]# echo "78A35114F798"|sed -r ":a;s/Bw{2}/:&/;ta"
78:A3:51:14:F7:98
[root@centos7 temp]#
#这里表示匹配单词边界,B表示匹配非单词边界的其他任意字符
#当然也可以采用其他的方式实现:
[root@centos7 temp]# echo "78A35114F798"|sed -r "s/..B/&:/g"
78:A3:51:14:F7:98
[root@centos7 temp]#

T label在一次输入后只要没有替换命令被成功执行就跳转到label,如果省略了label,则跳转到整条命令结尾(即开始下一次读入)

z表示清除模式空间中内容,和s/.*//起相同的作用,但更有效。

更多例子 1、删除匹配行的上一行和下一行
#例如输入数据为命令seq 10的输出(当然也可以是任意其他文件内容)
#要求删除匹配5那一行的前一行和后一行
[root@centos7 temp]# seq 10|sed -n "$!N;/
5/{s/.*
//p;N;d};P;D"
1
2
3
5
7
8
9
10
2、合并奇偶数行
#输入数据为命令seq 11的输出,要求分别将奇数和偶数分别放在同一行
#输出第一行`1 3 5 7 9 11`,第二行`2 4 6 8 10`
[root@centos7 ~]# seq 11|sed -nr "$!N;2!G;s/([^
]+)
((.+)
)?(.+)
(.+)/4 1
5 3/;h;$p"
1 3 5 7 9 11
2 4 6 8 10 
[root@centos7 ~]# 
3、合并多文件
#文本a.txt的内容:
01 12510101 4001
02 12310001 4002
03 12550101 4003
04 12610001 4004
05 12810001 4005
06 12310001 4006
07 12710001 4007
08 12310001 4008
09 12810101 4009
10 12510101 4010
11 12310001 4011
12 12610001 4012
13 12310001 4013
#文本b.txt的内容:
A 12410101 2006/02/15 2009/01/31 4002
B 12310001 2006/08/31 2008/08/29 4001
C 12610001 2008/05/23 2008/05/22 4002
D 12810001 1992/12/10 1993/06/30 4001
E 12660001 1992/05/11 1993/06/01 4005
#要求输出a.txt内容中第二列和b.txt中第二列相同的行,并追加b.txt中对应的两个日期列。
#形如:02 12310001 4002 2006/08/31 2008/08/29
sed -rn "/^[01]/ba;H;:a;G;s/^((..)( .*)( [^
]+)).*3(( [^ ]*){2}).*/15/p" b.txt a.txt
#当然如果使用awk来处理的话,解决思路更容易理解一些:
awk "NR==FNR{a[$2]=$3FS$4;next}{if($2 in a)print $0,a[$2]}" b.txt a.txt

为加深对sed各种命令特性的理解,请自行分析这三个例子。

各种命令的组合使用,再加上正则表达式的强大能力,使得sed可以处理所有能够计算的问题。但由于代码可读性不强,理解起来比较困难,通常使用sed作为一个文本编辑器,对文本做非交互的流式处理。理解上述各个命令的含义,熟练使用它们,就会发现sed的强大之处。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/9679.html

相关文章

  • SegmentFault 技术周刊 Vol.19 - Linux 文本处理三利器

    摘要:所以,本期周刊将介绍命令行世界中最常用的文本处理命令三巨头,让它们带你初步领略命令行的强大。简单的,可以直接理解为是一个数据处理工具,倾向于将一行文本分成数个字段来处理,适合小型数据的处理。 showImg(https://sfault-image.b0.upaiyun.com/226/799/2267992322-586b7c52ed9fc); 之前看过一篇文章《当我们 chmod ...

    hightopo 评论0 收藏0
  • linux文本处理三剑客之sed,原来只需要掌握这些!!!

    摘要:流编辑器会在编辑器处理数据之前基于预先提供的一组规则来编辑数据流。同样达到了对文本处理的效果。编辑器会将该命令作用到包含指定文本模式的行上。插入和附加文本和其他编辑器类似,编辑器允许向数据流插入和附加文本行。  前言: shell脚本最常见的一个用途就是处理文本文件。检查日志文件、...

    gnehc 评论0 收藏0
  • Linux_《Linux命令行与shell脚本编程大全》第九章学习总结

    摘要:命令行与脚本编程大全第三版第十九章学习总结第十九章初识和本章内容学习编辑器编辑器入门编辑器基础文本处理编辑器编辑器被称作流编辑器,和普通的交互式文本编辑器恰好相反。编辑器可以根据命令来处理数据流中的数据。 时间:2017年12月07日星期四说明:本文部分内容均摘取自书籍《Linux命令行与shell脚本编程大全》,版权归原作者所有。《Linux命令行与shell脚本编程大全》(第三版)...

    justjavac 评论0 收藏1
  • 分钟学会SED

    摘要:创建了一个通用的行编辑器,最终变成为了。由自由软件基金组织开发和维护并且随着进行分发,因此,通常它也称作。在发送数据之后,模式空间将会被清空。只有当前置条件成功的时候,命令才会跳转到该标签。命令只有在前一个替换命令执行成功的时候才会执行。 本文承接之前写的三十分钟学会AWK一文,在学习完AWK之后,趁热打铁又学习了一下SED,不得不说这两个工具真的堪称文本处理神器,谁用谁知道!本文大部...

    leoperfect 评论0 收藏0
  • 玩转Linux - 神级工具 sed & awk

    摘要:动作说明,不见得会存在,一般代表选择进行动作的行数。替换,可以直接进行替换工作。注是以行为一次处理的单位,而以字段最小的处理单位。列出目前处理的行数那就是内的变量。 简介 本文主要介绍 Linux 系统的两个神级工具:sed 和 awk ,他们是Linux高手们必备的技能,很值得我们去研究的东西。 这里是我在网上书上收集的相关资料,因为这两个工具很有名也很重要,所以这些资料会帮助我更好...

    yibinnn 评论0 收藏0

发表评论

0条评论

flybywind

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<