Loading... <p>在Linux的世界中,有着一个文本三剑客的称呼,它们分别代表grep(文本过滤),sed(流编辑器),awk(gawk)(报告生成器)。</p> <p>它们是强大的文本处理工具,了解并掌握它们,可以让你对文本的处理更加从容和轻松。</p> <p>今天我们主要是围绕sed来进行分析。</p> <p><strong>一、初识sed</strong></p> <p>sed:Stream Editor</p> <p>从名字上也可以直观的了解到它是一个流编辑工具。何为流编辑器?就是把文本中的文字按照特定的分隔方式,进行数据流处理。sed就是基于这种方式,它是以换行符以分隔单位,对文本进行逐行的处理。</p> <hr /> <p><strong>二、初识sed的工作原理</strong></p> <p><img src="//cto.wang/usr/uploads/2016/07/20160703161228-26.png" title="1433667905304476.png" alt="blob.png" /></p> <p>前提:首先对于一个文本文件来说,它是由至上而下的一行或N行组成。</p> <p>1、当用sed命令对文本进行处理的时候,sed先读取对象的文本文件的第一行到模式空间中。</p> <p>2、当有内容进入“模式空间”时,sed的编辑命令对模式空间中的内容进行编辑操作(修改,替换,删除,追加,显示等等)</p> <p>3、模式空间中的内容编辑处理完成之后,sed把此内容通过标准输出(默认为显示器)打印出来,并删除模式空间中的内容。</p> <p>4、第一行处理结束。从新读取第二行的内容进行处理,直到最后一行。</p> <hr /> <p><strong>三、sed命令的基本语法</strong></p> <p> sed OPTIONS… [SCRIPT] [INPUTFILE…]</p> <p> 常用的选项:</p> <p> -n,–quiet: 不输出模式空间中的内容</p> <p> -i: 直接编辑原文件,默认不对原文件进行操作</p> <p> -e: 可以使用多个命令(脚本)进行操作</p> <p> -f /path/from/sed_script: 从指定的文本中读取处理脚本</p> <p> -r: 使用扩展正则表达式</p> <hr /> <p><strong>四、模式空间中的编辑操作</strong></p> <p>1、地址定界:</p> <p> 1)#:#为数字,指定要进行处理操作的行</p> <p> 2)$:表示最后一行,多个文件进行操作的时候,为最后一个文件的最后一行</p> <p> 3)/regexp/:表示能够被regexp匹配到的行</p> <p> regexp及基于正则表达式的匹配:关于正则表达式的请参考grep的基本用法详解中的【三、了解正则表达式】</p> <p> 4)/regexp/I:匹配是忽略大小写</p> <p> 5)\%regexp%: 任何能够被regexp匹配到的行,换用%(用其他字符也可以,如:#)为边界符号</p> <p> 6)addr1,addr2:指定范围内的所有的行(范围选定)</p> <p> 常用的以下几种表示方法:</p> <p> a)0,/regexp/:从起始行开始到第一次能够被regexp匹配到的行</p> <p> b)/regexp/,/regexp/:被模式匹配到的行内的所有的行</p> <p> c)#,#:#为数字,给定具体的行范围</p> <p> d)#,+N:#为数字,从#开始的行开始,向下N行的所有的行</p> <p> 7)first~step:指定起始的位置及步长,例如:1~2表示1,3,5…</p> <p>2、常用的编辑命令:</p> <p> 1)d:删除匹配到的行</p> <p> 2)p:打印模式空间中的内容</p> <p> 注意:sed默认情况下是把“模式空间”中的内容全部进行显示,p的意义在于把匹配到的行进行显示。</p> <p> 所以其显示的结果是“默认的显示内容+p要显示的内容”。</p> <p> 因此通常与-n选项一起使用,表示只显示匹配到的行。</p> <p> 3)a \text:append,表示在匹配到的行之后追加内容</p> <p> 4)i \text:insert,表示在匹配到的行之前追加内容</p> <p> 5)c \text:change,表示吧匹配到的行和给定的文本进行交换</p> <p> 6)s/regexp/replacement/flages:查找替换,把text替换为regexp匹配到的内容(其中/可以用其他字符代替,例如@)</p> <p> 可能会用到的特殊replacemen(通常replacement为固定的字符窜):</p> <p> \L:转换后面的内容第一个字母为小写字母</p> <p> \l:后面的内容全部转换成小写,直到遇到\E为止</p> <p> \U:转换后面的内容第一个字母为大写字母</p> <p> \u:后面的内容全部转换成大写,直到遇到\E为止</p> <p> \E:当以\L或\U开始的时候,\E意味着停止字符的转换</p> <p> 详情请参考:sed的官方文档</p> <p> 如果是replacement为变量时,用'$VAR'引用即可</p> <p> 常用的flages:</p> <p> <span style="color:#0c0c0c"> g:全局替换,默认只替换第一个</span></p> <p> <span style="color:#0c0c0c"> i: 不区分大小写</span></p> <p><span style="color:#0c0c0c"> <span style="color:#0c0c0c"> p:如果成功替换则打印</span></span></p> <p><span style="color:#0c0c0c"><span style="color:#0c0c0c"> 7)<span style="color:#0c0c0c">w /path/to/somefile:将匹配到的文件另存到指定的文件中</span></span></span></p> <p><span style="color:#0c0c0c"><span style="color:#0c0c0c"><span style="color:#0c0c0c"> 8)<span style="color:#0c0c0c">r /path/from/somefile:将读取指定的文件内容到匹配的行处(如果指定文件为多行时,追加到匹配行之后)</span></span></span></span></p> <hr /> <p><strong>五、知识点练习</strong></p> <p>1、显示文件中的偶数行:</p> <p> 1)用first~step的方式来实现,把奇数行删除,自然显示的事偶数行</p> <p><img src="//cto.wang/usr/uploads/2016/07/20160703161229-73.png" title="1433674927299412.png" alt="blob.png" /></p> <p> 2)不输出默认的显示内容,用p指定显示偶数行</p> <p><img src="//cto.wang/usr/uploads/2016/07/20160703161229-7.png" title="1433674837268964.png" alt="blob.png" /></p> <p>2、在含有“ftp”这个行的前面加上“#This is a command”</p> <p><img src="//cto.wang/usr/uploads/2016/07/20160703161229-45.png" title="1433675404141555.png" alt="blob.png" /></p> <p>3、把以/sbin/nologin结尾的行的小写字母全部替换成大写</p> <p> 1)先用/regexp/地址定界的来选定以/sbin/nologin结尾的行</p> <pre class="brush:bash;toolbar:false">#显示所有以/sbin/nologin$结尾的行 # sed -n '\#/sbin/nologin$#p' test.txt</pre> <p> 2)查找替换</p> <p> 查找所有的小写字符[a-z]</p> <p> 其中/\u&/中的&表示前面所匹配到的所有内容,所以/\u&/g为前面所匹配到的小写字母全部替换为大写字母</p> <p><img src="//cto.wang/usr/uploads/2016/07/20160703161229-53.png" title="1433677694908466.png" alt="blob.png" /></p> <p>4、把/etc/man.config文件所有不以#开头的行保存到/tmp/sed/man.txt的目录中</p> <p>其中多个脚本用-e来分别执行,其实用;也可以实现多个脚本的连接。例如:</p> <pre class="brush:bash;toolbar:false"># sed -n -e '/^#/d;w /tmp/sed/man1.txt' /etc/man.config</pre> <p><img src="//cto.wang/usr/uploads/2016/07/20160703161229-40.png" title="1433680275103645.png" alt="blob.png" /></p> <p>查看文件保存正常,/tmp/sed/man.txt,并且其显示内容也符合要求</p> <p><img src="//cto.wang/usr/uploads/2016/07/20160703161229-14.png" title="1433680350548582.png" alt="blob.png" /></p> <p>5、用sed命令修改/tmp/sed/inittab中的id:X:initdefault:修改为id:5:initdefault:(其中X为任意的数字)</p> <p><img src="//cto.wang/usr/uploads/2016/07/20160703161230-36.png" title="1433681581828629.png" alt="blob.png" /></p> <hr /> <p><strong>六、sed的知识扩展</strong></p> <p>在sed的工作原理图中我们了解到,sed不仅存在模式空间,也存在一个保持空间(hold space)。顾名思义,保存空间是一段sed独有的内存空间片段,可以暂时存放一些数据。</p> <p>其中与“保持空间”相关的编辑命令有:</p> <p> h:把模式空间中的内容覆盖到保存空间中的内容</p> <p> H:把模式空间中的内容追加到保存空间中(加在原有内容之后)</p> <p> g:把保持空间中的内容覆盖到模式空间中的内容</p> <p> G:把保持空间中的内容追加到模式空间中(加在原有内容之后)</p> <p> x:把模式空间中的内容和保持空间中的内容进行交换</p> <p> d:删除模式空间中的内容</p> <p> D:如果模式空间中的内容为多行时,删除模式空间中的第一行</p> <p> n:读取匹配到的行的下一行到模式空间中(覆盖原内容)</p> <p> N:读取匹配到的行的下一行到模式空间中(追加在原内容之后)</p> <p>例如:显示偶数行的时候就可以这样实现:sed -n 'n;p' FILE</p> <p>练习1、把文件的相邻两行合并为一行</p> <p><img src="//cto.wang/usr/uploads/2016/07/20160703161230-61.png" title="1433687542734286.png" alt="blob.png" /></p> <p>练习2、</p> <p>前提:/etc/services文件是记录了服务与端口号之间的映射关系</p> <p>1) 在此文件中选出21,22,25,53,80,443,8080的行并予以显示</p> <p>grep -E可以支持使用扩展正则表达式,所以可以使用|(或者)</p> <p><img src="//cto.wang/usr/uploads/2016/07/20160703161230-95.png" title="1433687963533423.png" alt="blob.png" /></p> <p>2)要求把右边有#注释的行的注释信息追加到此行的上一行</p> <pre class="brush:bash;toolbar:false"># cd /tmp/sed # vim script.txt #创建sed命令脚本 # # script.txt内容如下 h #追加模式空间的内容到保存空间 s@.*\(#.*\)@\1@ #有注释内容的行仅保留注释的内容,没有注释的行不做修改 s/^[^#].*//g #把非#开头的行给替换成空行 G #把保持空间中内容追加到当前行之后 //d #删除所有空白行</pre> <p>执行效果如下:<img src="//cto.wang/usr/uploads/2016/07/20160703161230-66.png" title="1433690286830300.png" alt="blob.png" /></p> <p>3)删除右侧的注释行,并保留以#行开头的注释行</p> <p>在script中追加s/[[:space:]]\+#.*//</p> <p><img src="//cto.wang/usr/uploads/2016/07/20160703161230-28.png" title="1433690575134431.png" alt="blob.png" /></p> <p>4)服务与服务之间加入空白行</p> <pre class="brush:bash;toolbar:false"># 在行之后追加空白行的方法 # sed 'G' filename</pre> <p><img src="//cto.wang/usr/uploads/2016/07/20160703161231-87.png" title="1433691831747427.png" alt="blob.png" /></p> <p>sed '/^#/!G;$d' 在非#开头的行之加入空白行,之后最后一行会多出一个空白行,用sed '$d'删除最后一行即可。</p> <hr /> <p><strong>七、总结</strong></p> <p>sed是一款强大的文本处理工具,它的强大就是基于这些小命令。</p> <p>Linux的哲学思想之一不就是,组合小任务来完成大任务。</p> <p>只要基础掌握扎实,即便再复杂的处理,也能一步一步慢慢地完成。</p> <p></p> 最后修改:2021 年 12 月 10 日 10 : 53 AM © 允许规范转载 赞赏 如果觉得我的文章对你有用,请随意赞赏 赞赏作者 支付宝微信