awk命令详解(二)

2.3 表达式和运算符

awk 允许使用正则表达式,根据正则表达式是否匹配当前行来选择执行独立代码块。以下示例脚本只输出bill中包含字符序列8613902700003的那些行:

awk '/8613902700003/ { print }' bill 

当然,可以使用更复杂的正则表达式:

/[0-9]*/ { print } 

下面列出正则表达式元字符:

字符描述
.可代替除一行之外的任何单个字符
*可代替零个或多个在它前面出现的字符
[chars]可代替chars中的任何一个字符,chars是一串字符序列。你可以用-符号来定义一个字符范围。如果^是chars中的第一个字符,那么将匹配没有在chars中指定的字符
^匹配一行的开头
$匹配一行的结尾
\把\后面的字符照常输出,通常用来转义(不使用特殊含义)一个元字符

除了使用正则表达式来选择行,我们也可以使用布尔表达式来选择行。使用方法是将布尔表达式放在代码块之前,仅当对前面的布尔表达式求值为真时,awk才执行代码块。以下示例脚本将输出bill中第四个字段等于8613902700003的所有行中的第三、四字段。如果当前行的第四个字段不等于8613902700003,awk将继续处理文件而不对当前行执行print语句:

$4 == "8613902700003" { print "OrgAddr: "$3, "\tDestAddr: "$4 } 

注意,代码块前的布尔表达式必须与代码块在同一行上。

awk 提供了完整的比较运算符集合,包括"=="、"<"、">"、"<="、">="和"!="。另外,awk还提供了"~"和"!~" 运算符,它们分别表示“匹配”和“不匹配”。它们的用法是在运算符左边指定变量,在右边指定正则表达式。例如:

$4 ~ /8613902700003/ { print "OrgAddr: "$3, "\tDestAddr: "$4 } 

awk还允许使用布尔运算符"||"(逻辑或)和"&&"(逻辑与),以便创建更复杂的布尔表达式:

( $3 == "8613902700001" ) && ( $4 == "8613902700003" ) { print } 

awk的另一个优点是它有完整的数学运算符集合。除了标准的加、减、乘、除,awk还允许使用指数运算符"^"、模运算符"%"和其它许多从C语言中借入的易于使用的赋值操作符。

这些运算符包括前后加减(i++、--j)、加/减/乘/除赋值运算符(a+=3、b*=2、c/=2.2、d-=6.2)。不仅如此,还有易于使用的模/指数赋值运算符(a^=2、b%=4)。

2.4 字符串化变量

awk变量“字符串化”是指所有awk变量在内部都是按字符串形式存储的。而且只要变量包含有效数字字符串,就可以对它执行数学操作,awk会自动处理字符串到数字的转换步骤。请看以下这个示例:

BEGIN   { x="0" } 
/^$/    { x=x+1 } 
END     { print "I found " x " blank lines. :)" } 

这个例子的功能是计算文件中空白行的数量,^$表示空行。如果做一个小实验,就可以发现如果某个特定变量不包含有效数字,awk在对数学表达式求值时会将该变量当作数字0处理。

3 第二部分:提高

3.1 处理多行

在这一节里,顺带着讲一下三个特别的变量:

Awk特殊变量描述
RS(row separate)表示记录分隔符
OFS(out filed separate)表示输出字段分隔符,在两个单独的字段间插入定义的字符串
ORS(out row separate)表示输出记录分隔符,在两个单独的记录间插入定义的字符串

第一部分我们讨论的都是一个记录占用一行的情况,如果要分析占据多行的记录,除了依靠FS,还需要设置RS(记录分隔符变量)。RS变量告诉awk当前记录什么时候结束,新记录什么时候开始。

为了便于讨论,我们依然首先在当前目录下生成一个通讯录文件address,其内容如下:

zhangsan
13712345678
zhs@hotmail.com

lisi
13012345678
ls@21cn.com
要处理这个文件,可以将每三行看作是一个独立的记录,一个记录包含三个字段。如下脚本将原记录由三行转换成一行输出:

BEGIN { 
    FS="\n" 
    RS="" 
} 
  
{ 
    print $1 ", " $2 ", " $3 
} 

此代码将产生以下输出:

zhangsan, 13712345678, zhs@hotmail.com
lisi, 13012345678, ls@21cn.com


在上面例子中,为了在三个字段之间插入一个逗号和空格,使用了", "。这个方法虽然有用,但比较难看。其实我们还有更好的方法,那就是设置变量OFS(输出字段分隔符)。OFS缺省情况下被设置成" "(单个空格)。使用如下脚本可以达到上面例子同样的效果:

BEGIN { 
    FS="\n" 
    RS="" 
    OFS=", " 
} 
  
{ 
    print $1, $2, $3 
} 

awk还有一个特殊变量ORS(输出记录分隔符)。ORS缺省情况下被设置成"\n",如果我们将其设为"\n\n",就可以使输出记录的间隔翻倍。例子就不举了,大家可以自己试试。个空格分隔记录(而不换行),将ORS设置成" "。

需要注意的是,使用上面的方法,最多只能处理一个记录占用三行的文本,象下面一个记录占据四行的通讯录,就处理不了了(大家可以试试看):

wangwu
13512345678
ww@163.com
wuhan, hubei
 要处理这种情况,代码最好考虑每个记录的字段数量,并依次打印每个记录。以下就是修正的代码:

BEGIN { 
    FS="\n" 
    RS="" 
    ORS="" 
} 
  
{  
        x=1 
        while ( x<NF ) { 
                print $x "\t" 
                x++ 
        } 
        print $NF "\n" 
} 

程序输出如下:

 wangwu 13512345678 ww@163.com wuhan, hubei

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值