sed 命令 解析及使用
来源:互联网 发布:汽车解剖软件 编辑:程序博客网 时间:2024/05/29 04:19
参考来源:sed命令详解
sed原理及sed命令格式 ,缓存区,模式空间
Sed工作原理/工作过程
sed是一个非交互式的流编辑器。所谓非交互式,是指使用sed只能在命令行下输入编辑命令来编辑文本,然后在屏幕上查看输出;而所谓流编辑器,是指sed每次只从文件(或输入)读入一行,然后对该行进行指定的处理,并将结果输出到屏幕(除非取消了屏幕输出又没有显式地使用打印命令),接着读入下一行。整个文件像流水一样被逐行处理然后逐行输出。
下面我们看一下sed的工作过程。
sed不是在原输入上直接进行处理的,而是先将读入的行放到缓冲区中,对缓冲区里的内容进行处理,处理完毕后也不会写回原文件(除非用shell的输出重定向来保存结果),而是直接输出到屏幕上。sed运行过程中维护着两个缓冲区,一个是活动的“模式空间(pattern space)”,另一个是起辅助作用的“暂存缓冲区(holding space)”。一般情况下,每当运行sed,sed首先把第一行装入模式空间,进行处理后输出到屏幕,然后将第二行装入模式空间替换掉模式空间里原来的内容,然后进行处理,以此类推。
一般情况下暂存缓冲区是用不到的,但有特殊的命令可以在模式空间与暂存缓冲区之间交换数据,后文将有介绍。由于sed对文本的所有操作都是在缓冲区里进行的,所以不会对原文件造成任何破坏。
Sed命令格式
sed [-Options] ['Commands'] filename
其中,Command是一个sed命令,sed命令一定要被包含在一对单引号中,以免被shell解释,其格式如下:[address-range][sed-command]或[Pattern-to-match][sed-command].
[address-range][sed-command]
[address-range]是指要处理的行的范围,又叫地址范围;
[pattern-to-match]是一个要匹配的模式,是一个正则表达;
sed-command是一个sed命令,用来对指定的行进行处理。
下面是一个简单的例子:
sed –n '1,3p' students
这个命令将文件students中的第1到3行打印到屏幕。注意,地址范围和sed命令之间没有空格,如果加入空格,sed也会将其忽略。参数-n用来取消默认输出。默认情况下,sed每读入一行到模式空间,无论是否对其进行处理,在读入下一行之前多要将模式空间中的内容输出到屏幕上。参数-n可以用来取消这种默认的输出,只有当用户用命令p时才将指定的行输出到屏幕。如果没有用参数-n而又对指定行执行了p命令,那么这些行将会被打印两次。
地址范围可以是一个数字,这个数字代表了一个行号;也可以是一个用逗号分隔的两个数字表示的范围(包括这两行)。范围可以是数字,正则表达式,或是两者的组合。
####[Pattern-to-match][sed-command]
[pattern-to-match]是一个要匹配的模式,sed将会对所有匹配的行执行sed-command。其实,这里的pattern-to-match也可以看作是一个地址范围,这个地址范围是所有与指定模式匹配的行的行号。因此sed的格式可以归纳为一种:
sed [-Options] ‘[address-range][sed-command]’ filename
示例:
sed -n '1,3 p' a.txt #sed 命令 -n(sed的命令行选项----取消标准输出) 1,3 (读到缓冲区处理的地址范围) p(sed命令--这个命令表示要怎样处理缓冲区的内容,p是打印输出缓存区内容)sed -n '1,3 s/11/88/p;' a.txt #把1,3行读到缓冲区,处理缓冲区操作是 s/11/88/p 即替换其中的第一个11为88 p是打印结果。这里的[sed-command]就是 s/11/18/p这一句了。sed -n '1,3 s/11/88/gp;' a.txt #把1,3行读到缓冲区,处理缓冲区操作是 s/11/88/gp 即替换其中的所有的(g命令表示所有,正则的全局匹配)11为88 p是打印结果。sed -n 's/11/88/gp' a.txt #这个命令,由于没有定义范围,sed默认逐行读内容到缓冲区,并使用s/11/88/gp 命令处理。即:每读一行处理一次。
下面看个复杂的:
sed -n ‘:lb; /start/,/end/{/end/! {$! {N;b lb}}}; s/333.*555/8888/; p;’ a.txt
sed -n ’
:lb
/start/,/end/{/end/! {$! {N;b lb}}}
s/333.*555/8888/
p
’ a.txt
上面的解释:
{}是sed命令里的语句块
:lb 是send的label 功能,类似,c语言里的goto lable功能。 lb 是label名称可以自已随便起
:lb; /start/,/end/{/end/! {$! {N;b lb}}}; 可以简化成:lb; /start/,{/end/! {\$! {N;b lb}}};
表示范围是/start/开始,{/end/! {$! {N;b lb}}};结束的内容读到缓冲区。
{N;b lb} 这一句N是下一行读入缓冲区,然后跳转到lb继续执行。
s/333.*555/8888/; p; 使用这个命令处理缓冲区的内容。
其中:
/end/! {$! {N;b lb}} 中,/end/! 如果不end 那么就 执行这个块{$! {N;b lb}},$!表示如果也不是结尾,就是N循环lb 的label块。 即:只要没有遇见end字符串(/end/!),也没到文档结尾($!),就是一直一行一行读内容到缓冲区。
3.命令与选项
sed命令告诉sed如何处理由地址指定的各输入行,如果没有指定地址则处理所有的输入行。
sed命令
3.2 sed选项
3.3示例使用
p命令
命令p用于显示模式空间的内容。默认情况下,sed把输入行打印在屏幕上,选项-n用于取消默认的打印操作。当选项-n和命令p同时出现时,sed可打印选定的内容。
sed '/my/p' datafile
默认情况下,sed把所有输入行都打印在标准输出上。如果某行匹配模式my,p命令将把该行另外打印一遍。
sed -n '/my/p' datafile
选项-n取消sed默认的打印,p命令把匹配模式my的行打印一遍。
d命令
命令d用于删除输入行。sed先将输入行从文件复制到模式空间里,然后对该行执行sed命令,最后将模式空间里的内容显示在屏幕上。如果发出的是命令d,当前模式空间里的输入行会被删除,不被显示。
sed '$d' datafile
删除最后一行,其余的都被显示
sed '/my/d' datafile
删除包含my的行,其余的都被显示
.3 s命令
sed 's/^My/You/g' datafile #命令末端的g表示在行内进行全局替换,也就是说如果某行出现多个My,所有的My都被替换为You。
sed -n '1,20s/My$/You/gp' datafile #取消默认输出,处理1到20行里匹配以My结尾的行,把行内所有的My替换为You,并打印到屏幕上。
sed 's#My#Your#g' datafile #紧跟在s命令后的字符就是查找串和替换串之间的分隔符。分隔符默认为正斜杠,但可以改变。无论什么字符(换行符、反斜线除外),只要紧跟s命令,就成了新的串分隔符。
.4 e选项
-e是编辑命令,用于sed执行多个编辑任务的情况下。在下一行开始编辑前,所有的编辑动作将应用到模式缓冲区中的行上。
sed -e '1,10d' -e 's/My/Your/g' datafile #选项-e用于进行多重编辑。第一重编辑删除第1-3行。第二重编辑将出现的所有My替换为Your。因为是逐行进行这两项编辑(即这两个命令都在模式空间的当前行上执行),所以编辑命令的顺序会影响结果。[root@db22 tmp]# sed '1,10d' sed-1.txteleventwelvethirteenfourteenfifteen[root@db22 tmp]# sed -e '1,10d' -e 's/teen/tine/g' sed-1.txteleventwelvethirtinefourtinefiftine[root@db22 tmp]#
.5 r命令
r命令是读命令。sed使用该命令将一个文本文件中的内容加到当前文件的特定位置上。
sed '/My/r introduce.txt' datafile #如果在文件datafile的某一行匹配到模式My,就在该行后读入文件introduce.txt的内容。如果出现My的行不止一行,则在出现My的各行后都读入introduce.txt文件的内容。
.6 w命令
sed -n '/hrwang/w me.txt' datafile
.7 a\ 命令
a\ 命令是追加命令,追加将添加新文本到文件中当前行(即读入模式缓冲区中的行)的后面。所追加的文本行位于sed命令的下方另起一行。如果要追加的内容超过一行,则每一行都必须以反斜线结束,最后一行除外。最后一行将以引号和文件名结束。
sed '/^hrwang/a\>hrwang and mjfan are husband\>and wife' datafile#如果在datafile文件中发现匹配以hrwang开头的行,则在该行下面追加hrwang and mjfan are husband and wife
.8 i\ 命令
i\ 命令是在当前行的前面插入新的文本。
.9 c\ 命令
sed使用该命令将已有文本修改成新的文本。
.10 n命令
sed使用该命令获取输入文件的下一行,并将其读入到模式缓冲区中,任何sed命令都将应用到匹配行紧接着的下一行上。
sed '/hrwang/{n;s/My/Your/;}' datafile注:如果需要使用多条命令,或者需要在某个地址范围内嵌套地址,就必须用花括号将命令括起来,每行只写一条命令,或这用分号分割同一行中的多条命令。
6.11 y命令
该命令与UNIX/Linux中的tr命令类似,字符按照一对一的方式从左到右进行转换。例如,y/abc/ABC/将把所有小写的a转换成A,小写的b转换成B,小写的c转换成C。
sed '1,20y/hrwang12/HRWANG^$/' datafile#将1到20行内,所有的小写hrwang转换成大写,将1转换成^,将2转换成$。#正则表达式元字符对y命令不起作用。与s命令的分隔符一样,斜线可以被替换成其它的字符。
12 q命令
q命令将导致sed程序退出,不再进行其它的处理。
sed '/hrwang/{s/hrwang/HRWANG/;q;}' datafile
.13 h命令和g命令
h : 把模式空间里的内容复制到暂存缓冲区
H: 把模式空间里的内容追加到暂存缓冲区
g: 把暂存缓冲区里的内容复制到模式空间,覆盖原有的内容
G: 把暂存缓冲区的内容追加到模式空间里,追加在原有内容的后面
#测试使用的文件如下:[root@db22 tmp]# cat sed-2.txtMy name is hrwang.Your name is mjfan.hrwang is mjfan's husband.mjfan is hrwang's wife.
h : 把模式空间里的内容复制到暂存缓冲区
H: 把模式空间里的内容追加到暂存缓冲区
[root@db22 tmp]# sed -e '/hrwang/h' -e '$G' sed-2.txtMy name is hrwang.Your name is mjfan.hrwang is mjfan's husband.mjfan is hrwang's wife.mjfan is hrwang's wife.#根据输出可以看到,h命令把模式空间中的内容复制到holding space时,会覆盖掉原来的内容,所以holding space中只保留了最后一行。[root@db22 tmp]# sed -e '/hrwang/H' -e '$G' sed-2.txtMy name is hrwang.Your name is mjfan.hrwang is mjfan's husband.mjfan is hrwang's wife.My name is hrwang.hrwang is mjfan's husband.mjfan is hrwang's wife.#根据输出可以看到,H命令把pattern space中的内容添加到holding space中[root@db22 tmp]#
通过上面两条命令,你会发现h会把原来暂存缓冲区的内容清除,只保存最近一次执行h时保存进去的模式空间的内容。而H命令则把每次匹配hrwnag的行都追加保存在暂存缓冲区。
[root@db22 tmp]# sed -e '/hrwang/H' -e '$g' sed-2.txtMy name is hrwang.Your name is mjfan.hrwang is mjfan's husband.My name is hrwang.hrwang is mjfan's husband.mjfan is hrwang's wife.[root@db22 tmp]# sed -e '/hrwang/H' -e '$G' sed-2.txtMy name is hrwang.Your name is mjfan.hrwang is mjfan's husband.mjfan is hrwang's wife.My name is hrwang.hrwang is mjfan's husband.mjfan is hrwang's wife.
通过上面两条命令,你会发现g把暂存缓冲区中的内容替换掉了模式空间中当前行的内容,此处即替换了最后一行。而G命令则把暂存缓冲区的内容追加到了模式空间的当前行后。此处即追加到了末尾。
.14
[root@db22 tmp]# sed '{1h;2,3H;4G}' sed-2.txtMy name is hrwang.Your name is mjfan.hrwang is mjfan's husband.mjfan is hrwang's wife.My name is hrwang.Your name is mjfan.hrwang is mjfan's husband.[root@db22 tmp]# sed '{1H;2,3h;4G}' sed-2.txtMy name is hrwang.Your name is mjfan.hrwang is mjfan's husband.mjfan is hrwang's wife.hrwang is mjfan's husband.
.观摩别人的案例
sed之:a;N;$!ba构建循环读入文件至pattern
sed之h;H和:a;N;ba使用精解(对段落进行操作)
示例解析1
例子来源:sed循环
考虑一下我们有一个待处理文本文件books.txt ,它有以下内容:(目前奇数行是书名,偶数行是作者)
A Storm of SwordsGeorge R. R. MartinThe Two TowersJ. R. R. TolkienThe AlchemistPaulo CoelhoThe Fellowship of the RingJ. R. R. TolkienThe PilgrimagePaulo CoelhoA Game of ThronesGeorge R. R. Martin
下面的例子是连接书名,并在一行用逗号分隔作者姓名。然后,它会搜索模式“Paulo”。如果能够匹配,它打印一个连字符(- )在该行的前面,否则跳转到打印行打印标签。
[root@db22 tmp]# sed -n 'h;n;H;xs/\n/,//Paulo/!b Prints/^/- /:Printp' books.txt#执行结果如下:A Storm of Swords,George R. R. MartinThe Two Towers,J. R. R. Tolkien- The Alchemist,Paulo CoelhoThe Fellowship of the Ring,J. R. R. Tolkien- The Pilgrimage,Paulo CoelhoA Game of Thrones,George R. R. Martin
初看起来,上面的脚本可能看起来神秘。让我们看看这是什么情况。
最初sed读入pattern space第一行即书名,holding space为空。
- h命令:模式缓冲区被复制到holding space。现在,这两个缓冲区包含了本书即标题A Storm of Swords.
- n命令:读入下一行到模式空间。现在模式缓冲区包含George R. R. Martin
- H命令:将模式空间的内容添加到暂存缓冲区(holding space)
- x命令:交换暂存缓冲区与模式空间中的内容,此时可以再次对模式空间应用/pattern/,就像每读入一行到模式空间中那样。
- 现在模式空间中的内容为:“A Storm of Swords,George R. R. Martin(换行)The Two Towers,J. R. R. Tolkien”
s/\n/,/ :将换行符替换为“,”,此时模式空间中的内容就变成了“A Storm of Swords,George R. R. Martin,The Two Towers,J. R. R. Tolkien”
- /Paulo/!b Print :这一条命令匹配Paulo,目前没有匹配到,所以不执行,直接打印模式空间中的内容:“A Storm of Swords,George R. R. Martin(换行)The Two Towers,J. R. R. Tolkien” ,p命令:打印;完成后继续读入下一行,执行
- 第三次读入处理后,模式空间的内容为:”The Alchemist,Paulo Coelho” 此时匹配到 /Paulo/!b Print,!是对所选行之外的所有行直接跳转到Print,而匹配到Paulo的行则继续执行
s/^/- /
,从而完成替换,最后输出- The Alchemist, Paulo Coelho
! :对所选行以外的所有行应用命令
[root@db22 tmp]# sed -n 'h;n;H;xs/\n/,//Paulo/b Prints/^/- /:Printp' books.txt#去掉b Print之前的!号,输出如下:- A Storm of Swords,George R. R. Martin- The Two Towers,J. R. R. TolkienThe Alchemist,Paulo Coelho- The Fellowship of the Ring,J. R. R. TolkienThe Pilgrimage,Paulo Coelho- A Game of Thrones,George R. R. Martin
去掉!则是对匹配到Paulo的行跳转到Print,匹配不到的会执行到替换语句。
为了提高可读性,每个sed命令被放置在一个单独的行。然而,人们可以选择将所有命令在一行中,命令之间用分号分隔,如下所示:
[jerry]$ sed -n 'h;n;H;x;s/\n/, /;/Paulo/!b Print; s/^/- /; :Print;p' books.txt
sed循环
- sed 命令 解析及使用
- sed 命令全解析
- sed命令解析
- Sed命令解析
- Linux sed命令解析
- sed命令解析
- sed命令解析
- linux shell tr命令及sed命令使用
- sed原理及sed命令格式
- sed 命令的使用及shell判断语句
- sed命令使用详解
- sed命令使用
- sed命令使用详解
- sed命令使用详解
- sed命令使用详解
- sed命令使用详解
- sed命令使用详解
- sed 命令 使用 总结
- 【Web】Javascript多项式计算器
- Cannot resolve symbol 'permission'
- Children's Game UVA
- Unknown error: Unable to build: the file dx.jar was not loaded from the SDK folder!
- Java 任务调度框架 Quartz《一》
- sed 命令 解析及使用
- 深入解析array_merge函数的用法 php
- getopt函数,命令选项解析函数的分析
- 什么是分布式系统
- Servlet
- BZOJ 4569: [Scoi2016]萌萌哒 并查集+倍增
- 我的面经
- Linux学习笔记--Tcpdump
- Qt 非静态成员函数作为线程函数?