(二十一) Sed编辑器高级部分

    技术2022-07-11  156

    Sed编辑器高级部分

    前一篇文章 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8tgF6eS6-1593678401710)(https://blog.csdn.net/Leslie_LN/article/details/106852597)]我们介绍的所有sed编辑器命令都是针对的***一行数据***进行操作的;假如我们要匹配查找“this is leslie”短语,但如果这个短语分布在两行,用普通sed编辑器命令来处理文本就不可能成功;针对这种情况,sed编辑器包含了三个处理多行文本的特殊命令:

    N:将数据下一行加进来创建一个多行组来处理D:删除多行中的一行P:打印多行中的一行

    1.1 多行命令

    1.1.1 next命令

    1.单行next命令 小写的n命令:告诉sed编辑器移动到数据流中的下一行文本

    流程:

    (1)、查找匹配行 (2)、移动到下一行 (3)、执行命令行列表命令

    合并文本行

    单行的next命令会将数据流中的下一文本行移动到模式空间;多行的next命令会将下一行添加到模式空间中已有的文本后,将数据流中两行文本合并到同一个模式空间中,文本仍然用换行符分隔,但sed编辑器现在会将两行文本当做一行文本处理;

    如:

    查找含有first的那行文本,读入模式空间N命令将下一行文本合并到first那行后面替换命令将换行符替换为空格,文本文件中的两行在编辑器的输出中成了一行

    ***另外一个典型应用:***替换位于两行文字的文本短语

    on Tuesday,the Linux System Administrator's group meeting will be held. Thank you for your attendance. All System Administrators should attend.

    这儿替换System Administrator’s,注意第一处是位于两行之间,第二处是位于最后一行;

    这只是替换了跨多行的短语替换,如果单行有匹配的短语也需要替换:

    ***注意:***当N命令执行最后一行时,由于没有下一行可读了,N命令就会将编辑器停止;

    这儿演示按照书上解释会出现最后一行不会匹配的,按照书上说说所有这儿应该将位于同行的替换命令移动到N命令之前,这样就不会出现上面最后一行未被正确替换的情况:

    但是实际演示,好像并不会[P448]:

    1.1.2 多行删除命令

    单行删除命令(d):删除模式空间中的当前行;

    当N和d命令一起使用时:删除的模式空间中的两行如:

    多行删除命令(D):只删除模式空间中的第一行;

    比如:删除文本中第一行空白行

    这儿如果不和N命令使用,很难删除指定的空白行:

    sed '/^$/d' data4

    删除的文本中所有空白行;

    1.1.3 多行打印命令(P)

    只打印多行模式空间中的第一行;

    1.2 保持空间与模式空间

    sed编辑器对应着两块缓冲区(保存文本),即模式空间与保持空间;

    模式空间:保存带检查的文本

    保存空间:保存临时文本,默认是空白行;

    sed编辑器提供了五条操作模式、保持空间的命令:

    This is the header line. This is the first data line. This is the second data line. This is the last line.

    执行:sed -n ‘/first/ {h;p;n;p;g;p}’ data4

    执行步骤:

    首先匹配含有first的行读入模式空间h:将模式空间内容复制到保持空间p:打印模式空间内容即第一行n:移动到第二行,读入模式空间p:打印模式空间内容即第二行g:复制保持空间内容即第一行到模式空间,此时会先清空模式空间之前的内容p:答应模式空间内容即第一行内容

    1.3 排除命令(!)

    放在命令前,相当于对地址取反,对特定行执行命令;

    如:

    sed '/header/!p' data4

    相当于除了含有header那行不打印外,其他行都打印;

    1.4 改变流

    1.4.1 分支(b)

    格式:

    [地址]b [标签]

    地址:决定哪些行会触发分支命令

    标签:决定可要跳转到的位置,省略这跳转到脚本末尾;以冒号开始:即(:标签名)要指定标签,将它添加到b命令后即可;

    2、3行会触发分支命令,由于没有指定分支,即跳转到脚本末尾不会执行后面的连个替换命令;

    如果指定标签:

    用伪代码解释:

    if(2,3){ 执行标签后命令 }else{ 执行整个命令脚本,包括标签后的命令 }

    1.4.2 测试(t)

    格式:

    根据替换命令结果跳转到某个标签;如果没有指定标签,

    伪代码解释:

    if(替换命令匹配成功){ 跳转到指定标签 }else{ }

    格式:

    [地址]t [标签]

    1.5 模式替代

    假如我们替换.at结尾的一个三个字母的单词,在匹配模式中我们可以用 .通配符来表示一个字符,但是在替代模式中无法正确匹配这个通配符,比如:可能是cat、hat…

    echo "the cat sleeps in his hat" |sed 's/.at/.at/' 输出结果: the .at sleeps in his .at

    比如这里替模式的.并不是代表任意字符的特殊在字符,表示的仅仅就是“.”这个字符

    sed编辑器提供了“&”符号 在替代模式中表示匹配的对应文本;如:我们我为对应文本加上双引号:

    echo "the cat sleeps in his hat"| sed 's/.at/"&"/ 输出结果:the "cat" sleeps in his hat

    &提取的是对应的整个匹配文本,如果你只想替换其中一部分文本,这时就需要借助于子模式:

    在匹配中()包裹要提取的一部分文本,在替换模式中 /1、/2…来提取对应文本,这里的数值1:对应第一个子模式,2对应第二个子模式,以此类推…

    注意:这儿必须使用转义字符将他们标示为分组字符,而不是普通的圆括号,这跟转义其他特殊字符正相反;

    echo "this is is leslie,hello world" | sed 's/\(this\) is/\1/' 输出:this is leslie,hello world

    实例:对一个比较大的数字插入,

    echo "1112345678" | sed '{ :start s/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/p t start}' 输出: 1112345,678 1112,345,678 1,112,345,678 1,112,345,678

    1.6 在脚本中使用sed

    当编辑器脚本很长时,如果 每次使用时都键入整个脚本,可想而知得多繁琐。可以将编辑器命令放到***shell包装脚本***中,包装脚本充当着编辑器脚本和命令行之间的中间角色;

    在Shell脚本中可以将普通的shell变量即参数和sed编辑器脚本一起使用,比如:将命令行参数作为sed 编辑器脚本输入:

    #!/bin/bash sed -n '1!G;h;$p' S1 运行Shell脚本: ./test data4

    1.6.1 重定向sed输出

    默认情况,sed编辑器会将脚本的结果输出到STDOUT,在shell脚本中可以使用"$()"将sed编辑器命令输出重定向到一个变量中;

    比如:

    #!/bin/bash result=$(echo "1112345678" | sed '{ :start s/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/p t start}')

    1.7 sed使用工具

    1.7.1 为文本行增加行间距

    G命令:是追加保持空间内容到模式空间后面,前面我们说了,默认情况下,保持空间的为空白的即空白行;

    sed '$!G' data4

    我将看到相邻两行间将多出一个空白行;

    1.7.2 给文本中的行编号

    前面我说了借助于“=”来显示行号

    可以看见输出行号与文本是两行显示的,借助前面学习的N命令就可实现在每行文本行前显示行号:

    Processed: 0.009, SQL: 9