【转载】三十分钟学会SED

本文承接之前写的三十分钟学会AWK一文,在学习完AWK之后,趁热打铁又学习了一下SED,不得不说这两个工具真的堪称文本处理神器,谁用谁知道!本文大部分内容依旧是翻译自Tutorialspoint上的入门教程,这次是 Sed Tutorial 一文,内容做了一些删减和补充,增加了一些原文中没有提及到的语法和命令的讲解,并且对原文所有的示例都一一进行了验证,希望本文对大家学习和了解Sed有所帮助。

文中用到的测试文件可以在 https://github.com/mylxsw/sed-demo找到。

本文将会持续修正和更新,最新内容请参考我的 GITHUB 上的 程序猿成长计划 项目,欢迎 Star。

概述

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从输入流(文件,管道或者标准输入)中读取一行并且存储到它叫做 模式空间(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 "1d\n2d\n5d" > 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标签,打印出该行内容。

posted on 2019-02-19 15:24  xueyue77  阅读(374)  评论(0编辑  收藏  举报

导航