加入收藏 | 设为首页 | 会员中心 | 我要投稿 云计算网_泰州站长网 (http://www.0523zz.com/)- 视觉智能、AI应用、CDN、行业物联网、智能数字人!
当前位置: 首页 > 服务器 > 系统 > 正文

如何学会SED

发布时间:2022-01-09 03:51:32 所属栏目:系统 来源:互联网
导读:怎么学会SED,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。 下文中用到的测试文件可以在 https://github.com/mylxsw/sed-demo找到。 概述 SED的英文全称是 Stream EDitor,它是一个简单
怎么学会SED,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。
 
下文中用到的测试文件可以在 https://github.com/mylxsw/sed-demo找到。
 
概述
 
SED的英文全称是 Stream EDitor,它是一个简单而强大的文本解析转换工具,在1973-1974年期间由贝尔实验室的Lee E.  McMahon开发,今天,它已经运行在所有的主流操作系统上了。
 
McMahon创建了一个通用的行编辑器,最终变成为了SED。SED的很多语法和特性都借鉴了ed编辑器。设计之初,它就已经支持正则表达式,SED可以从文件中接受类似于管道的输入,也可以接受来自标准输入流的输入。
 
SED由自由软件基金组织(FSF)开发和维护并且随着GNU/Linux进行分发,因此,通常它也称作 GNU  SED。对于新手来说,SED的语法看起来可能有些神秘,但是,一旦掌握了它的语法,你就可以只用几行代码去解决非常复杂的任务,这就是SED的魅力所在。
 
SED的典型用途
 
SED的用途非常广泛,例如:
 
文本替换
选择性的输出文本文件
从文本文件的某处开始编辑
无交互式的对文本文件进行编辑等
工作流
 
在本章中,我们将会探索SED是如何工作的,要想成为一个SED专家,你需要知道它的内部实现。SED遵循简单的工作流:读取,执行和显示,下图描述了该工作流:
 
怎么学会SED
 
读取: SED从输入流(文件,管道或者标准输入)中读取一行并且存储到它叫做 模式空间(pattern buffer) 的内部缓冲区
执行: 默认情况下,所有的SED命令都在模式空间中顺序的执行,除非指定了行的地址,否则SED命令将会在所有的行上依次执行
显示: 发送修改后的内容到输出流。在发送数据之后,模式空间将会被清空。
在文件所有的内容都被处理完成之前,上述过程将会重复执行
需要注意的几点
 
模式空间 (pattern buffer) 是一块活跃的缓冲区,在sed编辑器执行命令时它会保存待检查的文本
默认情况下,所有的SED命令都是在模式空间中执行,因此输入文件并不会发生改变
还有另外一个缓冲区叫做 保持空间 (hold  buffer),在处理模式空间中的某些行时,可以用保持空间来临时保存一些行。在每一个循环结束的时候,SED将会移除模式空间中的内容,但是该缓冲区中的内容在所有的循环过程中是持久存储的。SED命令无法直接在该缓冲区中执行,因此SED允许数据在  保持空间 和 模式空间之间切换
初始情况下,保持空间 和 模式空间 这两个缓冲区都是空的
如果没有提供输入文件的话,SED将会从标准输入接收请求
如果没有提供地址范围的话,默认情况下SED将会对所有的行进行操作
示例
 
让我们创建一个名为 quote.txt 的文本文件,文件内容为著名作家Paulo Coelho的一段名言
 
$ vi quote.txt  There is only one thing that makes a dream impossible to achieve: the fear of failure.   - Paulo Coelho, The Alchemist
为了理解SED的工作流,我们首先使用SED显示出quote.txt文件的内容,该示例与cat命令类似
 
$ sed '' quote.txt There is only one thing that makes a dream impossible to achieve: the fear of failure. - Paulo Coelho, The Alchemist
在上面的例子中,quote.txt是输入的文件名称,两个单引号是要执行的SED命令。
 
首先,SED将会读取quote.txt文件中的一行内容存储到它的模式空间中,然后会在该缓冲区中执行SED命令。在这里,没有提供SED命令,因此对该缓冲区没有要执行的操作,***它会删除模式空间中的内容并且打印该内容到标准输出,很简单的过程,对吧?
 
在下面的例子中,SED会从标准输入流接受输入
 
$ sed ''
当上述命令被执行的时候,将会产生下列结果
 
There is only one thing that makes a dream impossible to achieve: the fear of failure.  There is only one thing that makes a dream impossible to achieve: the fear of failure.
在这里,***行内容是通过键盘输入的内容,第二行是SED输出的内容。
 
从SED会话中退出,使用组合键ctrl-D (^D)
 
基础语法
 
本章中将会介绍SED中的基本命令和它的命令行使用方法。SED可以用下列两种方式调用:
 
sed [-n] [-e] 'command(s)' files  sed [-n] -f scriptfile files
***种方式在命令行中使用单引号指定要执行的命令,第二种方式则指定了包含SED命令的脚本文件。当然,这两种方法也可以同时使用,SED提供了很多参数用于控制这种行为。
 
让我们看看如何指定多个SED命令。SED提供了delete命令用于删除某些行,这里让我们删除***行,第二行和第五行:
 
首先,使用cat命令显示文件内容
 
$ cat books.txt  1) A Storm of Swords, George R. R. Martin, 1216  2) The Two Towers, J. R. R. Tolkien, 352  3) The Alchemist, Paulo Coelho, 197  4) The Fellowship of the Ring, J. R. R. Tolkien, 432  5) The Pilgrimage, Paulo Coelho, 288  6) A Game of Thrones, George R. R. Martin, 864
现在,使用SED移除指定的行,为了删除三行,我们使用-e选项指定三个独立的命令
 
$ sed -e '1d' -e '2d' -e '5d' books.txt 3) The Alchemist, Paulo Coelho, 197 4) The Fellowship of the Ring, J. R. R. Tolkien, 432 6) A Game of Thrones, George R. R. Martin, 864
我们还可以将多个SED命令写在一个文本文件中,然后将该文件作为SED命令的参数,SED可以对模式空间中的内容执行文件中的每一个命令,下面的例子描述了SED的第二种用法
 
首先,创建一个包含SED命令的文本文件,为了便于理解,我们使用与之前相同的SED命令
 
$ echo -e "1dn2dn5d" > commands.txt  $ cat commands.txt 1d  2d  5d
接下来构造一个SED命令去执行该操作
 
$ sed -f commands.txt books.txt 3) The Alchemist, Paulo Coelho, 197 4) The Fellowship of the Ring, J. R. R. Tolkien, 432 6) A Game of Thrones, George R. R. Martin, 864
标准选项
 
SED支持下列标准选项:
 
-n 默认情况下,模式空间中的内容在处理完成后将会打印到标准输出,该选项用于阻止该行为
    $ sed -n '' quote.txt
-e 指定要执行的命令,使用该参数,我们可以指定多个命令,让我们打印每一行两次:
    $ sed -e '' -e 'p' quote.txt     There is only one thing that makes a dream impossible to achieve: the fear of failure.     There is only one thing that makes a dream impossible to achieve: the fear of failure.
。Paulo Coelho, The Alchemist
 
。Paulo Coelho, The Alchemist
 
-f 指定包含要执行的命令的脚本文件
$ echo "p" > commands     $     $ sed -n -f commands quote.txt     There is only one thing that makes a dream impossible to achieve: the fear of failure.
。Paulo Coelho, The Alchemist
 
GNU选项
 
这些选项是GNU规范定义的,可能对于某些版本的SED并不支持。
 
-n, --quiet, --slient:与标准的-n选项相同
-e script,--expression=script:与标准的-e选项相同
-f script-file, --file=script-file:与标准的-f选项相同
--follow-symlinks:如果提供该选项的话,在编辑的文件是符号链接时,SED将会跟随链接
-i[SUFFIX],--in-place[=SUFFIX]:该选项用于对当前文件进行编辑,如果提供了SUFFIX的话,将会备份原始文件,否则将会覆盖原始文件
-l N, --line-lenght=N:该选项用于设置行的长度为N个字符
--posix:该选项禁用所有的GNU扩展
-r,--regexp-extended:该选项将启用扩展的正则表达式
-u, --unbuffered:指定该选项的时候,SED将会从输入文件中加载最少的数据,并且更加频繁的刷出到输出缓冲区。在编辑tail  -f命令的输出,你不希望等待输出的时候该选项是非常有用的。
-z,--null-data:默认情况下,SED对每一行使用换行符分割,如果提供了该选项的话,它将使用NULL字符分割行
循环
 
与其它编程语言类似,SED提供了用于控制执行流的循环和分支语句。
 
SED中的循环有点类似于goto语句,SED可以根据标签(label)跳转到某一行继续执行,在SED中,我们可以定义如下的标签:
 
:label  :start  :end  :up
在上面的示例中,我们创建了四个标签。
 
要跳转到指定的标签,使用 b 命令后面跟着标签名,如果忽略标签名的话,SED将会跳转到SED文件的结尾。
 
b标签用于无条件的跳转到指定的label。
 
为了更好地理解SED中的循环和分支,让我们创建一个名为books2.txt的文本文件,其中包含一些图书的标题和作者信息,下面的示例中会合并图书的标题和作者,使用逗号分隔。之后搜索所有匹配“Paulo”的行,如果匹配的话就在这一行的开头添加-,否则跳转到Print标签,打印出该行内容。
 
$ cat books2.txt A Storm of Swords George R. R. Martin The Two Towers J. R. R. Tolkien The Alchemist Paulo Coelho The Fellowship of the Ring J. R. R. Tolkien The Pilgrimage Paulo Coelho A Game of Thrones George R. R. Martin  $ sed -n ' h;n;H;x s/n/, / /Paulo/!b Print s/^/- / :Print p' books2.txt A Storm of Swords , George R. R. Martin The Two Towers , J. R. R. Tolkien - The Alchemist , Paulo Coelho The Fellowship of the Ring , J. R. R. Tolkien - The Pilgrimage , Paulo Coelho A Game of Thrones , George R. R. Martin
乍看来上述的代码非常神秘,让我们逐步拆解一下
 
***行是h;n;H;x这几个命令,记得上面我们提到的 保持空间 吗?***个h是指将当前模式空间中的内容覆盖到  保持空间中,n用于提前读取下一行,并且覆盖当前模式空间中的这一行,H将当前模式空间中的内容追加到 保持空间  中,***的x用于交换模式空间和保持空间中的内容。因此这里就是指每次读取两行放到模式空间中交给下面的命令进行处理
接下来是 s/n/, / 用于将上面的两行内容中的换行符替换为逗号
第三个命令在不匹配的时候跳转到Print标签,否则继续执行第四个命令
:Print仅仅是一个标签名,而p则是print命令
为了提高可读性,每一个命令都占了一行,当然,你也可以把所有命令放在一行
 
$ sed -n 'h;n;H;x;s/n/, /;/Paulo/!b Print; s/^/- /; :Print;p' books2.txt
关于h,H,x命令参考官方手册 sed, a stream editor 3.6 Less Frequently-Used Commands节
 
分支
 
使用 t 命令创建分支。只有当前置条件成功的时候,t 命令才会跳转到该标签。
 
t命令只有在前一个替换(s)命令执行成功的时候才会执行。
 
让我们看一些前面章节中的例子,与之前不同的是,这次我们将打印四个连字符"-",而之前是一个。
 
$ sed -n ' h;n;H;x s/n/, / :Loop /Paulo/s/^/-/ /----/!t Loop p' books2.txt A Storm of Swords , George R. R. Martin The Two Towers , J. R. R. Tolkien ----The Alchemist , Paulo Coelho The Fellowship of the Ring , J. R. R. Tolkien ----The Pilgrimage , Paulo Coelho A Game of Thrones , George R. R. Martin
在上面的例子中,前面两行与上一节中讲的作用一致,第三行定义了一个Loop标签,接下来匹配存在“Paulo”的行,如果存在则在最前面添加一个-,接下来是我们这里的重点:
 
/----/!t  Loop这一行首先检查上面添加-之后是否满足四个-,如果不满足则跳转到Loop继续执行第三行,这样不停的追加-,***如果改行满足前面有四个-才继续往下执行。
 
为了提高可读性,我们将每一个SED命令独立一行,我们也可以在同一行中使用:
 
sed -n 'h;n;H;x; s/n/, /; :Loop;/Paulo/s/^/-/; /----/!t Loop; p' books.txt
模式空间和保持空间
 
模式空间
 
对任何文件的来说,最基本的操作就是输出它的内容,为了实现该目的,在SED中可以使用print命令打印出模式空间中的内容。
 
首先创建一个包含行号,书名,作者和页码数的文件,在本文中我们将会使用该文件,你也可以创建任何其它的文件,但是这里我们就创建一个包含以下内容的文件
 
$ vi books.txt  1) A Storm of Swords, George R. R. Martin, 1216  2) The Two Towers, J. R. R. Tolkien, 352  3) The Alchemist, Paulo Coelho, 197  4) The Fellowship of the Ring, J. R. R. Tolkien, 432  5) The Pilgrimage, Paulo Coelho,288  6) A Game of Thrones, George R. R. Martin, 864
执行p命令
 
$ sed 'p' books.txt 1) A Storm of Swords, George R. R. Martin, 1216  1) A Storm of Swords, George R. R. Martin, 1216  2) The Two Towers, J. R. R. Tolkien, 352  2) The Two Towers, J. R. R. Tolkien, 352  3) The Alchemist, Paulo Coelho, 197  3) The Alchemist, Paulo Coelho, 197  4) The Fellowship of the Ring, J. R. R. Tolkien, 432  4) The Fellowship of the Ring, J. R. R. Tolkien, 432  5) The Pilgrimage, Paulo Coelho, 288  5) The Pilgrimage, Paulo Coelho, 288  6) A Game of Thrones, George R. R. Martin, 864  6) A Game of Thrones, George R. R. Martin, 864
你可能会疑惑,为什么每一行被显示了两次?
 
你还记得SED的工作流吗?默认情况下,SED将会输出模式空间中的内容,另外,我们的命令中包含了输出命令p,因此每一行被打印两次。但是不要担心,SED提供了-n参数用于禁止自动输出模式空间的每一行的行为
 
$ sed -n 'p' books.txt  1) A Storm of Swords, George R. R. Martin, 1216  2) The Two Towers, J. R. R. Tolkien, 352  3) The Alchemist, Paulo Coelho, 197  4) The Fellowship of the Ring, J. R. R. Tolkien, 432  5) The Pilgrimage, Paulo Coelho, 288  6) A Game of Thrones, George R. R. Martin, 864
行寻址
 
默认情况下,在SED中使用的命令会作用于文本数据的所有行。如果只想将命令作用于特定的行或者某些行,则需要使用 行寻址 功能。
 
在SED中包含两种形式的行寻址:
 
以数字形式表示的行区间
以文本模式来过滤行
两种形式都使用相同的语法格式
 
[address]command
数字方式的行寻址
 
在下面的示例中SED只会对第3行进行操作
 
$ sed -n '3p' books.txt 3) The Alchemist, Paulo Coelho, 197
当然,我们还可以让SED输出某些行。在SED中使用逗号,分隔输出行号的范围,例如下面的代码会输出出2-5行的内容
 
$ sed -n '2,5 p' books.txt  2) The Two Towers, J. R. R. Tolkien, 352  3) The Alchemist, Paulo Coelho, 197  4) The Fellowship of the Ring, J. R. R. Tolkien, 432  5) The Pilgrimage, Paulo Coelho, 288

(编辑:云计算网_泰州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读