2010年11月17日星期三

正则表达式、sed与awk

课程名称
UNIX系统与软件开发环境

教学章节
正则表达式, 流编辑(sed), 模式搜索与处理(awk)

教学目的
掌握正则表达式的概念及用法,了解流编辑和模式搜索与处理

教学重点
正则表达式



教学难点
信号、位置参数、函数和子shell

知识点
正则表达式的概念及用法,流编辑和模式搜索与处理

教学时间


班级


教学器具
课件;多媒体播放系统

教学过程


第十章 shell编程

10.1 正则表达式

正则表达式是由一个或多个字符或元字符(meta-characters)组成的串。

普通字符包括大、小写字母和数字,而元字符则是具有特殊意义的字符。

支持模式搜索的命令一般都支持正则表达式。正则表达式在不同的系统中实现可能是不同的。

正则表达式包含的内容

字符集:在指定位置上匹配的一个或多个字符;

计数:指定其前面的字符重复的次数。比如“*”、“?”、“+”;

位置字符:特殊字符集,用于标明位置,比如行首、行末等;

具有特殊意义的字符。

有三种形式的正则表达式:

SRE(simple regular expression):传统UNIX支持这种正则表达式;

BRE(basic regular expression):ISO POSIX-2支持这种正则表达式;

ERE(extended regular expression):ISO POSIX-2也支持这种正则表达式。

ERE与BRE在用法上不尽相同,且ERE比BRE有更丰富的语法,但是ERE不是BRE的超集,一些BRE的表达式若不加修改,则在ERE中不能正常使用。

在Linux系统中还有ARE(advanced regular expression)是对ERE的扩展,ERE的表达式可直接在ARE上使用。

在有些UNIX系统中awk,egrep使用ERE,而其它程序比如,ed,ex,expr,grep,sed和vi使用BRE。

10.1.1 字符集

1. 元字符及示例

.:匹配除换行后以外的其他字符,a.c匹配abc,adc等

*:匹配0或多个前面刚出现的字符或正则表达式,aa*匹配a,aa,aaa,…

?:匹配其前面正则表达式0次或1次出现(ERE),bb?匹配b或bb

+:匹配其前正则表达式的1次或多次出现(ERE),(ab)+匹配ab,abab,…

^:^经常在[]内用于起动非匹配列表,[^ab]不匹配a或b

^:位置字符表示行首,^abc匹配行首为abc的行

$:位置字符表示行末,ter$匹配行末为ter的行

[ ],[^ ]:匹配或不匹配其中的一个字符。如果在选择集中包含],则它必须是第一个,[Qq]uery匹配Query和query。Str[^ea]ng匹配strong但不匹配strang

|:从多个选项选择(ERE),((auto)|(dog)matic)匹配automatic或dogmatic

\:转义字符;将其后面的一个字符变为普通字符,\”匹配字符”

( ):BRE组或子表达式。定义在圆括号的字符串以备后用。以后1到9表示前面保存的正则表达式,((auto)|(dog)matic)匹配automatic或dogmatic

\( \):ERE组或子表达式。保存在圆括号的字符串以备后用。以后\1到\9表示前面保存的正则表达式,\(more\) and \1匹配more and more

\<:在一个字的开始匹配其后正则表达式,\:在一个字的结尾匹配其前的正则表达式,ble\>匹配以ble结尾的词

\{l\},\{l,},\{l,u\}:匹配指定数量的重复,l为下界,u为上界(ERE),(ab)\{2\}匹配abab

{l},{l,},{l,u}:匹配指定数量的重复,l为下界,u为上界(BRE),(is{2}){2}:ississ

[. .]:组合类。匹配多个字符组合;[[.ijx.]]不同于[ijx],[[.ijx.]]匹配ijx

[= =]:相等类。匹配相同字符,[d[=e=]f]:[deeeef]

[: :]:类字符,[:digit:]定义数字类

2. 类字符

[:alnum:]:字符和数字,0~9,a~z,A~Z

[:alpha:]:字符,A~Z,a~z

[:blank:]:白空格。POSIX只包括空格和tab键

[:cntrl:]:控制字符

[:digit:]:数字 0~9

[:xdigit:]:十六进制字符,0~9,a~z

[:graph:]:制表符

[:lower:]:小写字符,a~z

[:upper:]:大写字符,A~Z

[:print:]:可打印字符

[:punct:]:标点符号,.,?,!

4. ERE匹配字符集

[=,=]; [:,:]; [., .]:等价类、字符类和联合类

*,+,?,{l},{l,}{l,u}:匹配0个或多个

\character:(通过\实现)特殊字符

^,$:位置字符

[ ]:括号表达式

|:多种选择

( ):组表达式

10.1.2 shell正则表达式

shell正则表达式和正则表达式在某些方面存在着不同。例如case模式匹配的是shell变量,文件模式匹配的是文件名。Shell的正则表达式的字符集如下:

?:等于“.”,代表任意字符,且不匹配“.”

\character:通过转义字符实现对特殊字符的匹配

[ ], [!…]:与正则表达式同

[. .], [= =], [: :]:同正则表达式,可用于find,ksh,vi

():同ERE,只匹配其中的一个表达式。适用于ksh,vi等

*:等同ERE

+:等同ERE;适用于ksh,vi

?:等同ERE;适用于ksh,vi

{expr1,expr2[,expr3], …}:为{ }中的表达式,产生匹配模式。适用于csh,ksh,vi

|:等同于ERE

&:连接字符

10.2 流编辑(sed)

功能:流编辑,对它的输入流进行按指定格式的转换。

sed使用脚本语言对输入流进行加工,脚本可以在命令行或文件中输入。

用法:sed [OPTIONS]… { scripts } [input-file] …

参数:-n,--quiet:抑制不必要的输出,若不使用-n,则输出操作过程的每一行;-e script:在命令行加入脚本;-f script-file:从指定文件中读取脚本;-r,--regexp-extended:使用扩展的正则表达式。

说明:在sed的命令行中,若没有使用-e或-f指定脚本,则它的第一个非选项变量将作为脚本,而其它的变量将作为输入文件,若无输入文件,则使用标准输入。sed的输出对象为标准输出,若输出到文件可使用输出重定向。

sed的地址形式:

begine_num~step:从bebine_num开始每step行执行一次

$:最后一行

L1,L2:从L1到L2行

L1,+N:从L1到L1+N行

L1,~N:从L1到行号为N的一个倍数的行

/regexp/:与模式regexp匹配的行

\cregexpc:与模式regexp匹配的行,c为任意字符

sed脚本中的部分命令

;:脚本命令分隔符 #:注释

{ }:命令组 :label:标号,设置跳转目标

=:显示当前行行号 D:删除指定行(不影响原输入文件)

L:显示当前行内容 Q/q:立即退出sed

R/r file:从文件中追加文本/行

T/t/b [label]:跳转到标号label,若不指定label则跳转到脚本末尾

!function:不执行function,founction的值有:=,l,d和p等

Wfile:将当前行内容写入文件file

a\text:在指定行后追加text文本

c\text:以字符串text取代当前行

i\text:在指定行前插入text文本

s/regexp/replacement/flag:查找regexp并用replacement替换之。Flag为:n-整数,只替换第n次出现;g-全部;p-如果替换,则显示;wfile-如果替换,则写入文件file

y/src/dest/:在指定范围内用dst内的字符集对应替代老字符集src的内容。dst与src的字符个数必须相等地。

sed示例:

1. 将ifile文件中的所有sysman替换成System Manager并输出到ofile

#sed -e 's/sysman/System Manager/g' ofile

2. 显示ifile文件中的所有注释行

#sed -e '/^#/!d' < ifile 3. 报告系统中所有(非)root用户的活动 #显示系统中root用户进程 #ps -ef | sed -e '/^[]*root/!d'

#显示系统中的非root用户进程

#ps -ef | sed -e '/^[]*root/d'

注:tab为tab键,Space为空格键

2. 删除文件ifile中的空行,并将其它的内容输出到ofile

#sed ’

/^$/d

/^[]*$/d

ofile

注:tab为tab键,可用\t表示,Space为空格键

也可写为:

#sed ’/^$/d; /^[]*$/d’ ofile

#sed ’/^$/d; /^ [:blank:]*$/d’ ofile

如果脚本命令较多,也可将整个脚本内容写入文件(比如e_script)中,此时命令的执行可如下进行:#sed –f e_script < ifile > ofile

10.3模式搜索与处理(awk)

功能:awk是一个用于模式搜索和处理的编程语言。

它最早的设计目的是针对报表生成的一种小巧且具表达力的语言,因此awk对于格式化结构的文件特别有效。

用法:

awk [options] -f progfile [--] file …

awk [options] [--] 'program' file …

参数:-f progfile:指定awk程序文件;-F fs:设置格式化文件的记录中域间分隔符;-v var=value:定义并指定变量的值。

记录和域:

awk的记录和域的概念与数据库里记录和域的概念类似。

在一个格式记录的文件里,它的每一“行”称为一个记录,而每一个记录又由域分隔符分隔的不同字段组成,这种字段就是记录中的域。

在awk中整个记录用$0表示,而组成记录的每个域依次表示为$1,$2,…等。

变量:

在awk中可以动态定义变量,只有当第一次被使用时变量才存在。由于是解释语言,变量可以是任何类型的,这取决于用户如何使用它。在awk中还可以使用数组。

awk的部分预定义变量:

ARGC:命令行参数的个数

ARGV:令行参数数组

ARGIND:命令行参数数组指针

ENVIRON:环境变量数组

ERRNO:文件等操作时出现错误的错误号

FILENAME:awk浏览的当前文件名

FIELDWIDTH:指定域宽,而不使用自动由域分割符分割的域宽

FNR:当前文件的记录数

FS:域分割符,默认为白空格

NF:当前文件的记录中的域个数

NR:当前记录数/号

OFS/ORS:输出域/记录分割符,默认为空格/回车

RS:输入时记录分割符,默认为回车键

BEGINE:定义开始语句块。开始块的内容只在awk开始时执行

END:定义结束语句块。结束块的内容只在awk执行结束时执行

操作符:

awk的操作符可以分为数字型、字符串型、变量型、域和数组元素等。部分操作符如下所示:

++,-- :自加自减运算符

?:用于C 语言表达式:x?y:x

+,-,*,/,% :算术运算符

||,&&,!:或、与、非

=,+=,*=,/=,%=,^=:赋值操作

~,!~ :匹配或不匹配

<,<=,==,!=,>= :关系运算

控制语句:

1. if语句:if (condition) statement [ else statement ]

2. while语句:while (condition) statement

3. do语句:do statement while (condition)

4. for语句:

for (expr1;expr2;expr3) statement

for (var in arry) statement

5. 控制转移和退出语句:Break,continue,exit

6. 语句组:{ statements }

常用函数:

gsub(r,s,):在$0中搜索字符串r并用s替代之

gsub(r,s,t):在字符串t中搜索字符串r并用s替换之

index(s,t):查找字符串s中t的位置

length(s):返回字符串s的长度

match(s,t):测试字符串s中是否包含匹配模式t的字符串

print :显示其变量的内容

sub(r,s):在$0中用s替换第一次出现的r

substr(s,p):返回字符串s中从p开始的子字符串

substr(s,p,n):返回字符串s中从p开始的含有n个字符的子字符串

toupper(s):返回符串s的大写形式

tolower(s):返回符串s的小写形式

awk程序的执行:awk由模式操作和函数语句序列组成。它们的格式为:

pattern { action statement }

function func_name ( param_list ) { statements }

模式操作包括模式和行为对,其中每个模式都是正则表达式。在awk执行时首先从命令行或程序文件中读取程序,然后解释并执行之。

在执行过程中,awk读取输入文件或标准输入,按顺序检查其中每一个记录是否能进行模式匹配,若能则执行行为操作。

awk使用示例:

1. 显示系统内root的进程,它们是什么,进程号是多少

#ps -ef | awk '/root/{ print $1, $2, $8 }'

2. 显示系统所非root用户在干什么,他们是谁?

#ps -ef | awk '!/root/{ print $1, $8 }'

3. 使用awk计算文件infile内数字的和。假设infile内容为数字串,且每个数字串占一行

#awk '{ sum += $1 }; END { print sum }' ifile

4. 显示系统内已经注册(创建)的所有用户(显示/etc/passwd内的所有用户)

#awk -F: '{ print $1 }' /etc/passwd

#-F:指定域分隔符为“:”





小结
正则表达式的概念及用法,流编辑和模式搜索与处理

没有评论:

发表评论