Software Design 中文版 03第2章:简单强大的文本处理工具_Software Design 中文版 03第2章:简单强大的文本处理工具试读-查字典图书网
查字典图书网
当前位置: 查字典 > 图书网 > 编程 > Software Design 中文版 03 > 第2章:简单强大的文本处理工具

Software Design 中文版 03——第2章:简单强大的文本处理工具

sed详解及用法 一提到sed,大家首先想到的可能是可以进行简单替换的文本过滤器吧。但是,sed 不仅能进行字符串或字符的替换,还可以做很多其他事情,比如特定行的处理及删除、使用脚本文件进行的处理、分支/ 循环处理等。本章我们来学习一下sed 的这些用法。 前 言 sed 是一个简单强大的文本处理工具。它起源很早,可以追溯到1973 年。sed 作为标准命令被收集到了UNIX 系的OS中,所以一旦发生问题时,这个命令可以起到帮助作用。即使不记住sed 的所有用法,只要学会一些基本用法,就可以将其充分应用于日常工作及和故障应对中了。 sed 的名称来源于Stream Editor(流编辑器),是针对输入流一口气执行所有事先准备好的处理的编辑器。它不像vi、Emacs那样的“对话式编辑器”一样可以看着界面编辑文章,而是事先把编辑的内容以“命令”的形式列举出来,对文本的加工是一气呵成的。所以适用于对一系列的文件反复执行相同变更的情况。 另外还可以从标准输入接收数据,所以对象数据就没必要一一保存成文件了。比如可以用sed 来处理由管道输出的其他命令的结果。 本章使用的是在Ubuntu 13.04上安装的GNUsed 4.2.1。像OS X、FreeBSD这样的BSD系列的UNIX安装的是BSD sed。因此,会有几个命令的选项和本章使用的GNU sed略有不同。使用的sed的版本可以用“--version”选项进行确认。 那么我们赶紧来看一下sed 的基本用法吧。实际上,使用sed 就是对文本文件进行过滤处理。我们准备一个如代码清单1 所示的源文件,按照下面这样执行sed,文件的一部分被替换后输出到标准输出上。 sed 将指定的文件逐行读入,根据给定的条件进行处理。把sed 当作单行脚本(One-Liner)使用,紧跟着“-e”选项,即可把处理内容作为脚本记述下来。如果替换成“-f”选项,就可以读入事先准备好的脚本文件。如果想把处理结果输出到文件,只需使用“>”进行重定向就可以了。 查看输出的文件,虽然一行中与模式匹配的地方有两处,但只有最开始的1 处被替换了。第1 行前半部分的“bbb”被替换成了“eee”,而后半部分的“bbb”却没有变。如果想把所有与模式匹配的地方都替换掉,需要在末尾加上标志“g”。 一般情况都是针对文件整体进行处理,使用地址的机会并不多,不过对于像日志数据这样的大量数据的分割编辑还是很便利的。 现在我们整理一下思路。图1 是sed 作为单行脚本使用时的基本形式。在理解脚本、地址、命令等sed 特有用语的基础上,接下来我们了解一下具体的使用方法。sed 的用法接下来对单行脚本或脚本文件中可以使用的各种命令、地址指定等进行说明。 命 令 至此为止介绍的sed 例子,都是用“s”命令进行字符串替换的。此外还有“d(删除)/p(数据输出)/y(替换1 个字符)/w(文件输出)/n(数据输入)”等各种各样的命令可以使用。这里介绍一下常用的s/y/d 命令。 s 命令(字符串替换)是sed 中被频繁使用的命令。在需要把某字符串替换为别的字符串的情况下使用。基本格式如下所示。 $ sed -e 's/原字符串/[替换后的字符串]/[标志]' ¬输入.txt [ 替换后的字符串] 和[ 标志] 是可以省略的。替换后的字符串省略时表示删除匹配的字符串。 原字符串可以用正则表达式表示。原字符串中含有“/”时,要在其前面加“(反斜杠)”进行转义处理,对于替换后的字符串也是同样的。 还可以把分隔符变为“/”以外的字符。在“s”后面指定要作为分隔符的字符。比如想把“/usr/local”替换成“/usr”时,将分隔符变为“!”后可按照如下所示执行。 虽说除了符号英文字母也可以作为分隔符来使用,不过那样就很难与替换字符串进行区分,所以还是尽量使用像/、# 这样的符号比较好。[ 替换后的字符串] 中出现“&”时表示和查找字符串一样。下面这个例子表示把“aaa”替换成“+aaa+”。 和原字符串的正则表达式一起使用是很便利的。与正则表达式匹配的字符串可以用“&”来引用。比如,如下所示,与“.*”匹配的字符串可以用“&”来表示,如果指定“output: &”,执行后各行的行头都加了“output:”。 不想做特别的处理,只是想把“&”字符替换掉时,使用“”进行转义处理指定为“&”即可。分隔符为“/”并且想替换字符“/”时,则指定为“/”即可(图2)。标志可以指定为“g(Global,把整个文章作为对象)/p(Print,表示置换后的结果)/w(Write,输出文件)”。也可以同时指定多个标志。标志“g”正如此前说明的那样,在把文章整体作为替换范围时使用。或者在sed 启动时加上“-g”选项也可以起到相同的效果。 标志“p”只表示发生替换的行,不过默认情况下不管是不是发生替换sed都会把输入数据输出到标准输出,所以如果只加标志“p”,会输出两行相同的内容。只想表示发生替换的行时,可以在sed 启动时加上“-n”选项来控制标准输出。 如果想把替换后的结果写到文件中,可以使用“w”标志。在w后面指定输出文件名。 此时在output.txt 中只输出匹配的行。如果同时还想输出不匹配的行,使用“w”命令会更简单一些。 输入可以执行多个脚本。稍后会详细说明。 y 命令(替换1 个字符)在希望把某个字符替换成另一个字符时使用。基本使用格式如下所示。 不能同时省略“替换前”和“替换后”。如果只替换一个字符,使用s 命令也可以,不过使用y 命令可以同时替换多个字符。比如要同时进行ax、by、cz 的替换,只需如下这样指定即可。 替换前字符的位置与替换后字符的位置要相同。因此,如果替换前与替换后的长度不同就会出错。比如英文小写字母替换成大写字母时如下所示。 d命令(删除) d 命令是删除指定行,并将剩余行进行输出的命令。删除第1~2 行的例子如下所示。$ sed -e '1,2d' input.txt1234567890!? !"#$%&'()?/_ 这里使用“地址”来指定行号,也可以省略。省略就表示删除所有行,输出结果则变为空。 $ sed -e 'd' input.txt ↑输出结果为空 另外,如果只执行d命令,输入文件是不会发生变化的,不会发生被删除内容所覆盖的现象。 地 址 只对特定的行进行处理时,就会用到“地址”(表1)。如果省略地址,所有的输入行都会当作处理对象。只指定一个地址时,只有指定行会作为处理对象。指定两个地址并以“,”分隔,这是范围指定。表示将从第一个行号开始到第二个行号结束的行作为处理对象。如果第二个数字与第一个相同或比第一个小时,只有第一个数字指定的行才会作为处理对象。最后一行用“$”指定。 $ sed -n -e '1,3p' input.txt ← 表示1~2行 $ sed -n -e '2,$p' input.txt ↑表示2~最后一行 地址除了使用数字,还可以使用正则表达式。比如,指定从以“aaa”开始的行到以“bbb”结尾的行为处理对象的例子如下所示。 $ sed -n -e '/^aaa/,/ddd$/p' input.txt aaabbbcccddd aaabbbcccddd AAABBBCCCDDD aaabbbcccddd 如果与结束行指定的模式相匹配的行不存在,一直到输入数据的结尾(最后一行)为止的行会作为处理对象。在寻找结束行的过程中,即使再次出现与开始行匹配的行也会被忽略。 对单行脚本来说很方便的选项sed 还有很多其他的选项,因此可以组成很复杂的脚本。比如一次性执行多个命令、覆盖输入文件、做成备份文件等,有很多对于单行脚本来说很方便的选项。 指定多个命令 以上介绍的sed 例子,都是一次只执行一个命令,实际上可以同时执行多个命令。命令和命令之间用分号“;”分隔。用于删除的d 命令和用于字符串替换的s 命令组合起来执行的例子如下所示。 $ sed -e '2d;s/aaa/eee/g' input.txt eeebbbcccddd eeebbbcccddd 1234567890!? !"#$%&'()?/_ 上面的例子表示对于输入数据,先删除第2 行后,再把aaa 替换成eee。指定两个及两个以上的命令时,对于文件的每一行(按顺序)执行各个命令。而不是对输入数据的所有行执行第一个命令后再执行第二个命令。在上例中,对第1 行执行d 命令,然后再执行s 命令,接着再对第二行执行d 命令和s 命令。如此反复操作直到最后一行。 还有其他的方法可以连接命令。在sed 的启动选项中,可以通过指定多个“-e' 脚本'”来执行多个命令。 $ sed -e '2d' -e 's/aaa/eee/g' input.txt eeebbbcccddd eeebbbcccddd 1234567890!? !"#$%&'()?/_ 文件输出 要把处理结果写到文件中,可以使用“>”重定向到文件,或者使用w命令写到文件。不过还可以在sed 启动时加上“-i”选项,将处理结果覆盖到源输入文件中。 $ sed -i -e 's/bbb/eee/' input.txt 甚至还可以将处理前的数据作为备份文件保存起来。在“-i”选项后面指定在备份文件名尾部要加的后缀。比如生成后缀为“.bak”的备份文件的例子如下所示。 $ sed -i.bak -e 's/bbb/eee/' input.txt $ ls input.txt input.txt.bak ↑新生成备份文件(input.txt.bak) 双直引号和单直引号 通常sed 在Bourne Shell 或C Shell 上执行。对于这样的shell,"(双直引号)/$(美元符)/`(重音符)/(反斜杠• 日元符号)等字符都有特殊的含义。因此,用sed指定脚本时,为了不作为特殊字符处理,需要用'(单直引号)括起来。 脚本中如果不使用正则表达式和符号,只使用单纯字符串的话,不用“'”括起来也可以进行处理。不过为了shell解释结果与预期结果不出现偏差,还是习惯使用单直引号为好。 还可以用“"”把脚本括起来。“-e " 脚本"”这样就可以使用shell 变量了。$USER(用户名)/$HOSTNAME(主机名)/$TERM(终端名)/$PWD(当前目录)等变量都可以作为模式来指定。 $ sed -e "s/$HOSTNAME/new_hostname/g" ¬ /etc/hosts ↑更改/etc/hosts中的主机名并输出 也可以使用用户自定义变量。下面这个例子中,定义用户自定义变量“$FROM”和“$TO”,并在sed 脚本中进行使用。脚本用“"”括起来了,把shell 变量进行展开,即为“s/aaa/eee/g”。 $ FROM="aaa" $ TO="eee" $ sed -e "s/$FROM/$TO/g" input.txt 在字符串很复杂的情况下,使用用户自定义变量可以简化脚本。在双直引号内使用特殊符号时,要用“”进行转义处理。 脚本文件的使用 sed 可以读取脚本文件进行执行。可以用sed 进行条件分支或使用标签进行循环等复杂的处理,这在对大量文件进行相同处理时是很便利的。 脚本文件的读取和执行 读取脚本文件进行执行,要使用如下所示的“-f”选项。 $ sed -f 脚本文件 输入文件 如果指定多个“-f”选项,按指定的顺序从文件中读取脚本进行执行。也可以同时使用“-e”选项和“-f”选项。在脚本文件中1 行记述1 个处理。 ↓用以下的内容做成文件sample.sed 1,3s/aaa/eee/g 3d 上述脚本文件(sample.sed)表示的处理是:对第1~3 行进行替换(aaa → eee),并删除第3 行。使用该脚本文件进行执行结果如下所示。 $ sed -f sample.sed input.txt eeebbbcccddd eeebbbcccddd AAABBBCCCDDD eeebbbcccddd 命令的组合 如果在脚本文件中使用“{...}”对命令进行组合,就可以对于一个地址执行多个命令。如下所示的脚本文件表示对第1~3 行执行3 个命令。

展开全文


推荐文章

猜你喜欢

附近的人在看

推荐阅读

拓展阅读

《Software Design 中文版 03》其他试读目录

• 第1章:从UNIX文本处理的基础开始 sed和AWK超级入门
• 第2章:简单强大的文本处理工具 [当前]
  • 大家都在看
  • 小编推荐
  • 猜你喜欢
  •