前言:
shell脚本最常见的一个用途就是处理文本文件。检查日志文件、读取配置 文件、处理数据元素,shell脚本可以帮助我们将文本文件中各种数据的日常处理任务自动化。但仅靠shell脚本命令来处理文本文件的内容有点力不从心的。如果想在shell脚本中处理任何类型的数据,掌握sed和gawk工具可以达到事半功倍的效果。企业开发中常用,高阶命令。
sed 编辑器被称作 流编辑器 ( stream editor),和普通的交互式文本编辑器恰好相反。流编辑器会在编辑器处理数据之前基于预先提供的一组规则来编辑数据流。 可以根据命令来处理数据流中的数据,这些命令要么从命令行中输入,要么存储 在一个命令文本文件中。
核心讲解:
在流编辑器将所有命令与一行数据匹配完毕后,它会读取下一行数据并重复这个过程。在流编辑器处理完流中的所有数据行后,它就会终止。由于命令是按顺序逐行给出的, sed 编辑器只需对数据流进行一遍处理就可以完成编辑操作。这使得 sed 编辑器要比交互式编辑器快得多,你可以快速完成对数据的自动修改。
有了上面核心理论的了解,下面我们就可以对sed进行实操演练了:
sed 使用的语法格式:
sed options script file
常用参数罗列:
重点说明:
script 参数指定了应用于流数据上的单个命令。如果需要用多个命令,要么使用 -e 选项在命令行中指定,要么使用 -f 选项在单独的文件中指定。有大量的命令可用来处理数据。
默认情况下, sed 编辑器会将指定的命令应用到 STDIN 输入流上。这样你可以直接将数据通过管道输入 sed 编辑器处理。
如截图中所见,这个例子在sed编辑器中使用了s命令。s命令会用斜线间指定的第二个文本字符串来替换第 一个文本字符串模式。在本例中是big test替换了test。
整个文本修改:
核心讲解:
在运行上面的例子时,结果都是立即就会显示出来的。这就是使用 sed编辑器的强大之处。我们可以同时对文本数据做出多处修改,而需要操作的时间是及其短暂的。需要注意的一点的是,sed编辑器并不会修改原来文本文件的数据。它只会将修改后的数据发送到STDOUT,我们可以查看源文本的数据依旧保持不变。
要在 sed 命令行上执行多个命令时,只要用 -e 选项就可以了。
操作演示:
操作详解:
两个命令都作用到文件中的每行数据上。命令之间必须用分号隔开,并且在命令末尾和分号 之间不能有空格。还有一种方式我们使用的很少,就是用shell中的次提示符来分隔命令,如下截图:
有时候我们有大量要处理的sed命令,此时我们就可以命令放在一个脚本文件里,文件通常以.sed 结尾,使用中我们只需要应用 -f 参数,就可以来读取文件中命令:
核心解说:
如上图,sed编辑器知道每行都是一条单独的命令。 跟在命令行输入命令一样,sed编辑器会从指定文件中读取命令,并将它们应用到数据文件中的 每一行上。同样达到了对文本处理的效果。
成功使用 sed 编辑器的关键在于掌握其各式各样的命令和格式,它们能够帮助你定制文本编辑行为。本节将介绍一些可以集成到脚本中基本命令和功能。上面章节我们已经懂得了如何用s 命令( substitute )来在行中替换文本。这个命令还有另外一些选 项能让事情变得更为简单。
上图中可以看到替换命令在替换多行中的文本时能正常工作,但默认情况下它只替换每行中出现的第一处。 要让替换命令能够替换一行中不同地方出现的文本必须使用替换标(substitutionflag),替换标记会在替换命令字符串之后设置。
替换标记分类:
- 数字,表明新文本将替换第几处模式匹配的地方;
- g,表明新文本将会替换所有匹配的文本;
- p,表明原先行的内容要打印出来;
- w file,将替换的结果写到文件中。
对比一以上两图,我们可以得出结论:
将替换标记指定为 2 的结果就是: sed 编辑器只替换每行中第二次出现的匹配模式。 g替换标记使你能替换文本中匹配模式所匹配的每处地方。
有时我们会在文本字符串中遇到一些不太方便在替换模式中使用的字符。 Linux 中一个常见的例子就是正斜线( / )。 替换文件中的路径名会比较麻烦。
上面我们可以发现,由于正斜线通常用作字符串分隔符,因而如果它出现在了模式文本中的话,必须用反斜线来 转义。这通常会带来一些困惑和错误。 要解决这个问题,sed编辑器允许选择其他字符来作为替换命令中的字符串分隔符,下例中我们就是使用感叹号用作字符串分隔符。
sed 的寻址模式分为两种:
- 以数字形式表示行区间
- 用文本模式来过滤出行
两种寻址的语法格式是相同的,sed编辑器会将指定的每条命令作用到匹配指定地址的行上。
[address]command或者是将特定地址的多个命令分组:address {command1command2command3}
当使用数字方式的行寻址时,可以用行在文本流中的行位置来引用。sed 编辑器会将文本流中的第一行编号为1 ,然后继续按顺序为接下来的行分配行号。 在命令中指定的地址可以是单个号,或是用起始行号、逗号以及结尾行号指定的一定区间范围内的行。
c.如果想将命令作用到文本中从某行开始的所有行,可以用特殊地址$.
/pattern/ command
必须用正斜线将要指定的pattern封起来。sed编辑器会将该命令作用到包含指定文本模式的行上。
如下面给的示例:修改用户Samantha的默认shell,可以使用sed命令。
该命令只作用到匹配文本模式的行上。虽然使用固定文本模式能帮你过滤出特定的值,就跟 上面这个用户名的例子一样,但其作用难免有限。sed 编辑器在文本模式中采用了一种称为 正则 表达式( regular expression )的特性来帮助你创建匹配效果更好的模式。
如果需要在单行上执行多条命令,可以用花括号将多条命令组合在一起。 sed 编辑器会处理地址行处列出的每条命令。
两条命令都会作用到该地址上。同样,也可以在一组命令前指定一个地址区间。
文本替换命令不是 sed 编辑器唯一的命令。如果需要删除文本流中的特定行,可以用删除命令。删除命令d名副其实,它会删除匹配指定寻址模式的所有行。使用该命令时要特别小心,如 果你忘记加入寻址模式的话,流中的所有文本行都会被删除。
笔记重点:
记住,sed编辑器不会修改原始文件。你删除的行只是从sed编辑器的输出中消失了。原始文件仍然包含那些“删掉的”行。
和其他编辑器类似,sed编辑器允许向数据流插入和附加文本行。两个操作的区别可能比较让人费解:
- 插入(insert)命令(i)会在指定行前增加一个新行;
- 附加(append)命令(a)会在指定行后增加一个新行。
这两条命令的费解之处在于它们的格式。它们不能在单个命令行上使用。你必须指定是要将行插入还是附加到另一行。格式如下:
sed '[address]command new line'
修改( change )命令允许修改数据流中整行文本的内容。它跟插入和附加命令的工作机制一样,你必须在 sed 命令中单独指定新行。
[ address ] y / inchars / outchars /
如图中输出中看到的,inchars模式中指定字符的每个实例都会被替换成outchars模式中 相同位置的那个字符。 转换命令是一个全局命令,也就是说,它会文本行中找到的所有指定字符自动进行转换,而不会考虑它们出现的位置。
替换命令包含一些可以用于文件的标记。还有一些 sed 编辑器命令也可以实现同样的目标,不需要非得替换文本。
[ address ]w filename
[ address ]r filename
后记:
虽然 shell 脚本本身完成很多事情,但单凭 shell 脚本通常很难处理数据。 Linux 提供了两个方便的工具来帮助处理文本数据。作为一款流编辑器, sed 编辑器能在读取数据时快速地自动处理数 据。必须给sed 编辑器提供用于处理数据的编辑命令。