设计Script时,有时候需修改脚本,例如:删除或置换某些关键词。像这种在Script执行过程动态修改文件的做法,称为流编辑。具有流编辑能力的工具,称为流编辑器(stream editer)。sed是这方面的佼佼者,可补Bash的不足。另外,Script执行时可能要制作报表,呈现各字段信息。传统上,能和Bash完美搭配的,非awk莫属。
本章将介绍这两个强大工具的基本用法,熟悉这两者,可让你的Script如虎添翼,威力大增。
13.1  正则表达式
在介绍sed和awk之前,要先具备正则表达式的基本知识。
正则表达式是组成“样式”的基本语法,而“样式”是运用sed和awk必备的能力。sed 和awk相同的运行方式是:只要符合“样式”的数据行,就对它执行指定的“操作”。因此,了解样式的基本语法,运用sed和awk才能得心应手。
何谓正则表达式
正则表达式是一种描述的方法,一种小型的语言,可表示某种样式或若干种样式的组合,它的威力在于仅需几个简单的符号,便可代表许多字符串共同的样子。这是固定样式无法比拟的,例如,样式Shell,只能比对固定的字符串,作用不大,但若改成sh*,却可比对 she、Shell、short等多种字符串,涵盖面
较大,因此,发挥的作用较强。
以下介绍正则表达式的语法:
.一点代表一个字符
. 代表任意的字符。
例1:样式 .T. ,代表3个字符,中间是T,左右两边是任意的一个字符。
例2:...
代表字符长度是3的字符串。若想比对 . 这个字符本身,需加上转义字符(\),写成\.。例如:样式data\....代表data.后接3个字符,如、data.cfg、data.123等,都符合这个样式,但data1234就不符合了,因为4个点最左边的那个点,已经用\转义其特殊意义,还原为.
这个字符本身,因此,\....和1234比对不符。
^ 在行首
^ 代表位置在行的开头。
例如:样式 ^Jack ,代表Jack 应出现在行首,才算符合样式。像Jack and Marry 123就符合此样式,但Hi Jack 就不符合,因为Jack 没有出现在该行的最前面。
$在尾部
$ 代表位置在行的最后面。
例如:样式123$,代表在行的最后面是123。像Jack and Marry 123即符合此样式。
[...] 字符集合
[...] 代表字符串行中的一个字符(长度为1个字符)。 例1:样式 [ABc],代表A 或B 或c 这3个字符中的一个。 例2:[Ss]ame 代表Same 或same 。 以下是常见的用法:
[A-Z] 一个大写字母 [a-z]  一个小写字母 [0-9]  一个数字
[^A-Z]  除了大写字母之外的一个字符 [^a-zA-Z]  一个非英文字母的字符
[^a-zA-Z0-9]
一个非英文字母、且非数字的字符
^
出现在括号里的第一个位置,代表“非/不是”之意。
* 出现0个以上
* 代表前面的(左邻)字符有0个或0个以上。
例如:样式aA*c ,代表A 这个字符可能出现0个或0个以上。例如:ac 、aAc 、aAAc 、aAAAc 都符合此样式。
\{...\} 指定符合的个数
指定前面的(左邻)字符的个数。
例如:\{3,5\} 表示前面的字符有3~5个。[a-z]\{3,5\}代表以小写字母组成的字符串,长度是3~5。
265
\(...\) 把比对符合的字符串暂时保存起来
例如:H\(...\)y 表示要保存H 和y 之间的3个字符。
若要提取保存的字符串,可用位置参数,\1代表第一个保存的字符串,\2代表第二个,其他类推。
13.2  sed 的用法
sed 是一种非交互式的流编辑器,可动态编辑文件。所谓非交互式是说,sed 和传统的文本编辑器不同,并非和使用者直接互动,sed 处理的对象是文件的数据流(称为stream/流)。sed 的工作模式是,比对每一数据行,若符合样式,就执行指定的操作。
Tip
本节介绍的sed 是指GNU 版的sed 。执行sed --version 可查看版本信息。
sed 的语法如下:
sed '样式命令' 文件
它的意思是说:如果文件中某一行符合“样式”,就执行指定的sed 命令,如删除(d )或取代(s )。
这里的“样式”使用一对//含括,表示寻之意;也可以指定数据行的范围,例如:1,6表示作用范围是由第1行到第6行;/AAA/,/DDD/表示作用范围是从含有 AAA 的数据行,到含有DDD 的数据行。
请特别注意:sed 并不会更改文件内容。sed 的工作方式是读取文件内容,经流编辑之后,把结果显示到标准输出。因此,如果想要存储sed 的处理结果,得自行运用转向输出将结果存成其他文件。
以下介绍sed 的各种用法:
z  sed
的用法1:删除某一段范围的数据行。
sed '1,4d' dataf1
把第1到第4行数据删除,剩下的显示出来。
d 是sed 的删除命令。 z  sed 的用法2:把含有“样式”的数据行删除。
sed '/La/d' dataf3
把含有La 的行删除,剩下的显示出来。其中,/ / 代表搜索之意。
sed '/[0-9]\{3\}/d' dataf3
把含有“3位数”的行删除,剩下的显示出来。
在样式[0-9]\{3\}中,\{3\} 表/ /要寻的是3个数字组成的字符串。
sed '/^$/d' dataf5
linux执行shell命令删除dataf5的空白行。^ 表开头,$ 表尾部,这两者之间没有任何字符,代表该行是一空白行。
z
sed 的用法3:把不含有“样式”的数据行删除。
sed '/La/!d' dataf3
把不含有La 的行删除,剩下的显示出来。 这里的!是否定的意思,表示不符合样式者。
z  sed 的用法4:把含有“样式”的数据行显示出来。
sed '/La/p' dataf3
把含有La 的行显示出来。其中,p 是sed 的命令,它会把目前的数据显示出来,
但因为sed 默认也会显示不符合的数据行,所以,应改用以下指令:
sed -n '/La/p' dataf3
选项-n 会抑制sed 显示出其他资料行的默认操作,只显示符合样式的数据行。 z  sed 的用法5:取代。
sed -n 's/La/Oo/p' dataf3
这里的s 是取代的意思,第一对//中含括的字符串(La )是搜索的目标,第二对//含括的是置换的字符串(Oo )。它会把数据行中的字符串La 换成Oo 。
请注意:上面这个指令,只会更换第一个出现的La 而已,如要全部置换,应再加上全局的命令g ,如下所示:
sed -n 's/La/Oo/gp' dataf3
这样就会把所有到的La 全换成Oo 了。 取代的用法,还有以下几个:
sed -n 's/La//p' dataf3
267