Chinaunix首页 | 论坛 | 博客
  • 博客访问: 372563
  • 博文数量: 80
  • 博客积分: 6032
  • 博客等级: 准将
  • 技术积分: 730
  • 用 户 组: 普通用户
  • 注册时间: 2005-07-05 20:07
文章分类

全部博文(80)

文章存档

2007年(1)

2006年(22)

2005年(57)

我的朋友

分类:

2005-07-05 21:03:04

awk条件操作符

awk内置变量

awk操作符

内置的字符串函数

==========================================================

awk条件操作符

操作符描述
< 小于
> = 大于等于
< = 小于等于
== 等于
!= 不等于
~ 匹配正则表达式
!~ 不匹配正则表达式

1. 匹配
为使一域号匹配正则表达式,使用符号'~'后紧跟正则表达式,也可以用if语句。awk中if后面的条件用()括起来。
观察文件grade.txt,如果只要显示brown腰带级别可知其所在域为field-4,这样可以写出表达式{if($4~/Brown/) print}意即如果field-4包含brown,打印它。如果条件满足,则打印匹配记录行。可以编写下面脚本,因为这是一个动作,必须用花括号{}括起来。

代码:
[root@Linux_chenwy sam]# awk '{if($4~/Brown/) print }' grade.txt
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansl 05/99 4712 Brown-2 12 30 28

匹配记录找到时,如果不特别声明,awk缺省打印整条记录。使用if语句开始有点难,但不要着急,因为有许多方法可以跳过它,并仍保持同样结果。下面例子意即如果记录包含模式brown,就打印它:
代码:
[root@Linux_chenwy sam]# awk '$4~/Brown/' grade.txt
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansl 05/99 4712 Brown-2 12 30 28


2. 精确匹配
假定要使字符串精确匹配,比如说查看学生序号48,文件中有许多学生序号包含48,如果在field-3中查询序号48,awk将返回所有序号带48的记录:
代码:
[root@Linux_chenwy sam]# awk '{if($3~/48/) print}' grade.txt
M.Tans 5/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 26 26


为精确匹配48,使用等号==,并用单引号括起条件。例如$3=="48"
代码:
[root@Linux_chenwy sam]# awk '$3=="48"' grade.txt
P.Bunny 02/99 48 Yellow 12 35 28
[root@Linux_chenwy sam]# awk '{if($3=="48") print}' grade.txt
P.Bunny 02/99 48 Yellow 12 35 28


3. 不匹配
有时要浏览信息并抽取不匹配操作的记录,与~相反的符号是!~,意即不匹配。像原来使用查询brown腰带级别的匹配操作一样,现在看看不匹配情况。表达式!~/Brown/,意即查询不包含模式brown腰带级别的记录并打印它。
注意,缺省情况下,awk将打印所有匹配记录,因此这里不必加入动作部分。
代码:
[root@Linux_chenwy sam]# awk '$4!~/Brown/' grade.txt
M.Tans 5/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26
P.Bunny 02/99 48 Yellow 12 35 28


可以只对field-4进行不匹配操作,方法如下:
代码:
[root@Linux_chenwy sam]# awk '{if($4!~/Brown/) print }' grade.txt
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansl 05/99 4712 Brown-2 12 30 28


如果只使用命令awk $4!="brown"{print } grade.txt,将返回错误结果,因为用引号括起了brown,将只匹配‘brown而不匹配brown-2和brown-3,当然,如果想要查询非brown-2的腰带级别,可做如下操作:
代码:
[root@Linux_chenwy sam]# awk '$4!="Brown-2" {print }' grade.txt
M.Tans 5/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 26 26


4. 小于
看看哪些学生可以获得升段机会。测试这一点即判断目前级别分field-6是否小于最高分field-7,在输出结果中,加入这一改动很容易。
代码:
[root@Linux_chenwy sam]# awk '{if($6<$7) print }' grade.txt
M.Tans 5/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26


5. 小于等于
对比小于,小于等于只在操作符上做些小改动,满足此条件的记录也包括上面例子中的输出情况。
代码:
[root@Linux_chenwy sam]# awk '{if($6 <= $7) print $1}' grade.txt
M.Tans
J.Lulu
J.Troll


6. 大于
代码:
[root@Linux_chenwy sam]# awk '{if($6 > $7) print $1}' grade.txt
P.Bunny
L.Tansl


7. 设置大小写
为查询大小写信息,可使用[ ]符号。在测试正则表达式时提到可匹配[ ]内任意字符或单词,因此若查询文件中级别为green的所有记录,不论其大小写,表达式应为'/[Gg]reen/'
代码:
[root@Linux_chenwy sam]# awk '/[Gg]reen/' grade.txt
M.Tans 5/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26


8. 任意字符
抽取名字,其记录第一域的第四个字符是a,使用句点.。表达式/^...a/意为行首前三个字符任意,第四个是a,尖角符号代表行首。
代码:
[root@Linux_chenwy sam]# awk '$1 ~ /^...a/' grade.txt
M.Tans 5/99 48311 Green 8 40 44
L.Tansl 05/99 4712 Brown-2 12 30 28


9. 或关系匹配
为抽取级别为yellow或brown的记录,使用竖线符|。意为匹配|两边模式之一。注意,使用竖线符时,语句必须用圆括号括起来。
代码:
[root@Linux_chenwy sam]# awk '$0 ~/(Yellow|Brown)/' grade.txt
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansl 05/99 4712 Brown-2 12 30 28

上面例子输出所有级别为Ye l l o w或B r o w n的记录。

使用这种方法在查询级别为G r e e n或g r e e n时,可以得到与使用[ ]表达式相同的结果。
代码:
[root@Linux_chenwy sam]# awk '/^M/' grade.txt
M.Tans 5/99 48311 Green 8 40 44


10. 行首
不必总是使用域号。如果查询文本文件行首包含M的代码,可简单使用下面^符号:
代码:
[root@Linux_chenwy sam]# awk '/^M/' grade.txt


复合表达式即为模式间通过使用下述各表达式互相结合起来的表达式:
引用:
&& AND : 语句两边必须同时匹配为真。
|| O R:语句两边同时或其中一边匹配为真。
! 非求逆


11. AND
打印记录,使其名字为‘P.Bunny且级别为Yellow,使用表达式($1=="P.Bunny" && $4=="Yellow" ),意为&&两边匹配均为真。完整命令如下:
代码:
[root@Linux_chenwy sam]# awk '{if ($1=="P.Bunny" && $4=="Yellow") print $0}' grade.txt
P.Bunny 02/99 48 Yellow 12 35 28


12. Or
如果查询级别为Yellow或Brown,使用或命令。意为"||"符号两边的匹配模式之一或全部为真。
代码:
[root@Linux_chenwy sam]# awk '{if ($4=="Yellow" || $4~/Brown/) print $0}' grade.txt
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansl 05/99 4712 Brown-2 12 30 28


原来不一定得加print,下面我自己对例一二做了一下
代码:
1
[root@Linux_chenwy sam]# awk '$4~/Brown/' grade.txt
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansl 05/99 4712 Brown-2 12 30 28


代码:
2
[root@Linux_chenwy sam]# awk '$3=="48"' grade.txt
P.Bunny 02/99 48 Yellow 12 35 28


代码:
[root@Linux_chenwy sam]# awk '$3="48"' grade.txt
M.Tans 5/99 48 Green 8 40 44
J.Lulu 06/99 48 green 9 24 26
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 48 Brown-3 12 26 26
L.Tansl 05/99 48 Brown-2 12 30 28


2中,我把=和==写错了,呵呵,一个是赋值,一个是等于

awk内置变量
awk有许多内置变量用来设置环境信息。这些变量可以被改变。表9-3显示了最常使用的一些变量,并给出其基本含义。

引用:
awk内置变量

ARGC 命令行参数个数
ARGV 命令行参数排列
ENVIRON 支持队列中系统环境变量的使用
FILENAME awk浏览的文件名
FNR 浏览文件的记录数
FS 设置输入域分隔符,等价于命令行- F选项
NF 浏览记录的域个数
NR 已读的记录数
OFS 输出域分隔符
ORS 输出记录分隔符
RS 控制记录分隔符


引用:
A R G C支持命令行中传入a w k脚本的参数个数。A R G V是A R G C的参数排列数组,其中每一元素表示为A R G V [ n ],n为期望访问的命令行参数。

E N V I R O N 支持系统设置的环境变量,要访问单独变量,使用实际变量名,例如E N V I R O N [“E D I TO R”] =“Vi”。

F I L E N A M E支持a w k脚本实际操作的输入文件。因为a w k可以同时处理许多文件,因此如果访问了这个变量,将告之系统目前正在浏览的实际文件。

F N R支持a w k目前操作的记录数。其变量值小于等于N R。如果脚本正在访问许多文件,每一新输入文件都将重新设置此变量。

F S用来在a w k中设置域分隔符,与命令行中- F选项功能相同。缺省情况下为空格。如果用逗号来作域分隔符,设置F S = ","。

N F支持记录域个数,在记录被读之后再设置。

O F S允许指定输出域分隔符,缺省为空格。如果想设置为#,写入O F S = " # "。

O R S为输出记录分隔符,缺省为新行( n)。

R S是记录分隔符,缺省为新行( n )。



NF、NR和FILENAME

要快速查看记录个数,应使用N R。比如说导出一个数据库文件后,如果想快速浏览记录个数,以便对比于其初始状态,查出导出过程中出现的错误。使用N R将打印输入文件的记录个数。print NR放在E N D语法中。
代码:
[root@chenwy sam]# awk 'END{print NR}' grade.txt
5


如:所有学生记录被打印,并带有其记录号。使用N F变量显示每一条读记录中有多少个域,并在E N D部分打印输入文件名。
[root@chenwy sam]# awk '{print NF,NR,$0} END{print FILENAME}' grade.txt
代码:
7 1 M.Tans 5/99 48311 Green 8 40 44
7 2 J.Lulu 06/99 48317 green 9 24 26
7 3 P.Bunny 02/99 48 Yellow 12 35 28
7 4 J.Troll 07/99 4842 Brown-3 12 26 26
7 5 L.Tansl 05/99       4712 Brown-2 12 30 28
grade.txt


在从文件中抽取信息时,最好首先检查文件中是否有记录。下面的例子只有在文件中至少有一个记录时才查询B r o w n级别记录。使用A N D复合语句实现这一功能。意即至少存在一个记录后,查询字符串B r o w n,最后打印结果。
代码:
[root@chenwy sam]# awk '{if (NR>0 && $4~/Brown/)print $0}' grade.txt
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansl 05/99   4712 Brown-2 12 30 28


N F的一个强大功能是将变量$ P W D的返回值传入a w k并显示其目录。这里需要指定域分隔符/。
代码:
[root@chenwy sam]# echo $PWD | awk -F/ ' {print $NF}'
sam


另一个例子是显示文件名。
代码:
[root@chenwy sam]# echo "/usr/local/etc/rc.sybase" | awk -F/ '{print $NF}'
rc.sybase



如果不指定域分割符,返回的如下:
代码:

[root@chenwy sam]# echo $PWD | awk  '{print $NF}'
/usr/sam
[root@chenwy sam]# echo "/usr/local/etc/rc.sybase" | awk '{print $NF}'
/usr/local/etc/rc.sybase

awk操作符
在a w k中使用操作符,基本表达式可以划分为数字型、字符串型、变量型、域及数组元素,前面已经讲过一些。下面列出其完整列表。

在表达式中可以使用下述任何一种操作符。

引用:
= += *= / = %= ^ = 赋值操作符
? 条件表达操作符
|| && ! 并、与、非(上一节已讲到)
~!~ 匹配操作符,包括匹配和不匹配
< <= == != >> 关系操作符
+ - * / % ^ 算术操作符
+ + -- 前缀和后缀


前面已经讲到了其中几种操作,下面继续讲述未涉及的部分。

1. 设置输入域到域变量名
在a w k中,设置有意义的域名是一种好习惯,在进行模式匹配或关系操作时更容易理解。
一般的变量名设置方式为n a m e = $ n,这里n a m e为调用的域变量名, n为实际域号。例如设置学生域名为n a m e,级别域名为b e l t,操作为n a m e = $ 1 ; b e l t s = $ 4。注意分号的使用,它分隔a w k命令。下面例子中,重新赋值学生名域为n a m e,级别域为b e l t s。查询级别为Ye l l o w的记录,并最终打印名称和级别。
代码:
[sam@chenwy sam]$ awk '{name=$1;belts=$4;if(belts ~/Yellow/) print name" is belt "belts}' grade.txt
P.Bunny is belt Yellow


2. 域值比较操作
有两种方式测试一数值域是否小于另一数值域。
1) 在B E G I N中给变量名赋值。
2) 在关系操作中使用实际数值。
通常在B E G I N部分赋值是很有益的,可以在a w k表达式进行改动时减少很多麻烦。
使用关系操作必须用圆括号括起来。
下面的例子查询所有比赛中得分在2 7点以下的学生。
用引号将数字引用起来是可选的,“2 7”、2 7产生同样的结果。
代码:
[sam@chenwy sam]$ awk '{if ($6<$7) print $0}' grade.txt
M.Tans 5/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26


第二个例子中给数字赋以变量名B A S E L I N E和在B E G I N部分给变量赋值,两者意义相同。
代码:
[sam@chenwy sam]$ awk 'BEGIN{BASELINE="27"} {if ($6J.Lulu 06/99 48317 green 9 24 26
J.Troll 07/99 4842 Brown-3 12 26 26


3. 修改数值域取值
当在a w k中修改任何域时,重要的一点是要记住实际输入文件是不可修改的,修改的只是保存在缓存里的a w k复本。a w k会在变量N R或N F变量中反映出修改痕迹。
为修改数值域,简单的给域标识重赋新值,如: $ 1 = $ 1 + 5,会将域1数值加5,但要确保赋值域其子集为数值型。
修改M . Ta n s l e y的目前级别分域,使其数值从4 0减为3 9,使用赋值语句$ 6 = $ 6 - 1,当然在实施修改前首先要匹配域名。
代码:
[sam@chenwy sam]$ awk '{if($1=="M.Tans") {$6=$6-1};print $1,$6,$7}' grade.txt
M.Tans 39 44
J.Lulu 24 26
P.Bunny 35 28
J.Troll 26 26
L.Tansl 30 28

代码:
[sam@chenwy sam]$ awk '{if($1=="M.Tans") {$6=$6-1;print $1,$6,$7}}' grade.txt
M.Tans 39 44


4. 修改文本域
修改文本域即对其重新赋值。需要做的就是赋给一个新的字符串。在J . Tr o l l中加入字母,使其成为J . L . Tr o l l,表达式为$ 1 = " J . L . Tr o l l ",记住字符串要使用双秒号( " "),并用圆括号括起整个语法。
代码:
[sam@chenwy sam]$ awk '{if($1=="J.Troll") $1="J.L.Troll"; print $1}' grade.txt
M.Tans
J.Lulu
P.Bunny
J.L.Troll
L.Tansl


5. 只显示修改记录
上述例子均是对一个小文件的域进行修改,因此打印出所有记录查看修改部分不成问题,但如果文件很大,记录甚至超过1 0 0,打印所有记录只为查看修改部分显然不合情理。在模式后面使用花括号将只打印修改部分。取得模式,再根据模式结果实施操作,可能有些抽象,现举一例,只打印修改部分。注意花括号的位置。
代码:
[sam@chenwy sam]$ awk '{if($1=="J.Troll") {$1="J.L.Troll"; print $1}}' grade.txt 
J.L.Troll

不知道为什么,我这里多了一个空行?

6. 创建新的输出域
在a w k中处理数据时,基于各域进行计算时创建新域是一种好习惯。创建新域要通过其他域赋予新域标识符。如创建一个基于其他域的加法新域{ $ 4 = $ 2 + $ 3 },这里假定记录包含3个域,则域4为新建域,保存域2和域3相加结果。
在文件g r a d e . t x t中创建新域8保存域目前级别分与域最高级别分的减法值。表达式为‘{ $ 8 = $ 7 - $ 6 }’,语法首先测试域目前级别分小于域最高级别分。新域因此只打印其值大于零的学生名称及其新域值。在B E G I N部分加入t a b键以对齐报告头。
代码:
[sam@chenwy sam]$ awk 'BEGIN{print "Name Difference"}{if($6<$7) {$8=$7-$6;print $1,$8}}' grade.txt
Name    Difference
M.Tans 4
J.Lulu 2


当然可以创建新域,并赋给其更有意义的变量名。例如:
代码:
[sam@chenwy sam]$ awk 'BEGIN{print "Name Difference"}{if($6<$7) {diff=$7-$6;print $1,diff}}' grade.txt
Name    Difference
M.Tans 4
J.Lulu 2


7. 增加列值
为增加列数或进行运行结果统计,使用符号+ =。增加的结果赋给符号左边变量值,增加到变量的域在符号右边。例如将$ 1加入变量t o t a l,表达式为t o t a l + = $ 1。列值增加很有用。许多文件都要求统计总数,但输出其统计结果十分繁琐。在a w k中这很简单,请看下面的例子。
将所有学生的‘目前级别分’加在一起,方法是t o t + = $ 6,t o t即为a w k浏览的整个文件的域6结果总和。所有记录读完后,在E N D部分加入一些提示信息及域6总和。不必在a w k中显示说明打印所有记录,每一个操作匹配时,这是缺省动作。
代码:
[sam@chenwy sam]$ awk '(tot+=$6); END{print "Club student total points :" tot}'
grade.txt
M.Tans 5/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansl 05/99 4712 Brown-2 12 30 28
Club student total points :155


如果文件很大,你只想打印结果部分而不是所有记录,在语句的外面加上圆括号()即可。
代码:
[sam@chenwy sam]$ awk '{(tot+=$6)}; END{print "Club student total points :" tot}' grade.txt
Club student total points :155


8. 文件长度相加
在目录中查看文件时,如果想快速查看所有文件的长度及其总和,但要排除子目录,使用ls -l命令,然后管道输出到a w k,a w k首先剔除首字符为d(使用正则表达式)的记录,然后将文件长度列相加,并输出每一文件长度及在E N D部分输出所有文件的长度。
本例中,首先用ls -l命令查看一下文件属性。注意第二个文件属性首字符为d,说明它是一个目录,文件长度是第5列,文件名是第9列。如果系统不是这样排列文件名及其长度,应适时加以改变。
下面的正则表达式表明必须匹配行首,并排除字符d,表达式为^ [ ^ d ]。
使用此模式打印文件名及其长度,然后将各长度相加放入变量t o t中。
代码:

[sam@chenwy sam]$ ls -l | awk '/^[^d]/ {print $9" "$5} {tot+=$5} END {print "total KB:" tot}'
...................
total KB:174144

内置的字符串函数

代码:
awk内置字符串函数
g s u b ( r, s ) 在整个$ 0中用s替代r
g s u b ( r, s , t ) 在整个t中用s替代r
i n d e x ( s , t ) 返回s中字符串t的第一位置
l e n g t h ( s ) 返回s长度
m a t c h ( s , r ) 测试s是否包含匹配r的字符串
s p l i t ( s , a , f s ) 在f s上将s分成序列a
s p r i n t ( f m t , e x p ) 返回经f m t格式化后的e x p
s u b ( r, s ) 用$ 0中最左边最长的子串代替s
s u b s t r ( s , p ) 返回字符串s中从p开始的后缀部分
s u b s t r ( s , p , n ) 返回字符串s中从p开始长度为n的后缀部分


g s u b函数有点类似于s e d查找和替换。它允许替换一个字符串或字符为另一个字符串或字符,并以正则表达式的形式执行。第一个函数作用于记录$ 0,第二个g s u b函数允许指定目标,然而,如果未指定目标,缺省为$ 0。
i n d e x(s,t)函数返回目标字符串s中查询字符串t的首位置。l e n g t h函数返回字符串s字符长度。
m a t c h函数测试字符串s是否包含一个正则表达式r定义的匹配。s p l i t使用域分隔符f s将字符串s划分为指定序列a。
s p r i n t函数类似于p r i n t f函数(以后涉及),返回基本输出格式f m t的结果字符串e x p。
s u b(r,s)函数将用s替代$ 0中最左边最长的子串,该子串被( r)匹配。
s u b(s,p)返回字符串s在位置p后的后缀。s u b s t r(s,p,n)同上,并指定子串长度为n。
现在看一看a w k中这些字符串函数的功能。

1. gsub
要在整个记录中替换一个字符串为另一个,使用正则表达式格式, /目标模式/,替换模式/。例如改变学生序号4 8 4 2到4 8 9 9:
代码:
[root@Linux_chenwy root]# cd /usr/sam
[root@Linux_chenwy sam]# awk 'gsub(/4842/,4899){print $0}' grade.txt
J.Troll 07/99 4899 Brown-3 12 26 26

代码:
[root@Linux_chenwy sam]# awk 'gsub(/4842/,4899)' grade.txt
J.Troll 07/99 4899 Brown-3 12 26 26


2. index
查询字符串s中t出现的第一位置。必须用双引号将字符串括起来。例如返回目标字符串B u n n y中n y出现的第一位置,即字符个数。
代码:
[root@Linux_chenwy sam]# awk 'BEGIN {print index("Bunny","ny")}' grade.txt
4


3. length
返回所需字符串长度,例如检验字符串J . Tr o l l返回名字及其长度,即人名构成的字符个数
代码:
[root@Linux_chenwy sam]# awk '$1=="J.Troll" {print length($1)" "$1}' grade.txt
7 J.Troll


还有一种方法,这里字符串加双引号。
代码:
[root@Linux_chenwy sam]# awk 'BEGIN{print length("A FEW GOOD MEN")}'
14


4. match
m a t c h测试目标字符串是否包含查找字符的一部分。可以对查找部分使用正则表达式,返回值为成功出现的字符排列数。如果未找到,返回0,第一个例子在A N C D中查找d。因其不存在,所以返回0。第二个例子在A N C D中查找D。因其存在,所以返回A N C D中D出现的首位置字符数。第三个例子在学生J . L u l u中查找u。
代码:
[root@Linux_chenwy sam]# awk 'BEGIN{print match("ANCD",/d/)}'
0
[root@Linux_chenwy sam]# awk 'BEGIN{print match("ANCD",/D/)}'
4
[root@Linux_chenwy sam]# awk '$1=="J.Lulu" {print match($1,"u")}' grade.txt
4


5. split
使用s p l i t返回字符串数组元素个数。工作方式如下:如果有一字符串,包含一指定分隔符- ,例如A D2 - K P 9 - J U 2 - L P - 1,将之划分成一个数组。使用s p l i t,指定分隔符及数组名。此例中,命令格式为( " A D 2 - K P 9 - J U 2 - L P - 1 ",p a r t s _ a r r a y," - "),s p l i t然后返回数组下标数,这里结果为4。
代码:
[root@Linux_chenwy sam]# awk 'BEGIN {print split("123-456-789",pats_array,"-")}'3


还有一个例子使用不同的分隔符。
代码:
[root@Linux_chenwy sam]# awk 'BEGIN {print split("123#456#789",myarray,"#")}'                                                        3

这个例子中,s p l i t返回数组m y a r r a y的下标数。数组m y a r r a y取值如下:
代码:
myarray[1]=123
myarray[2]=456
myarray[3]=789

结尾部分讲述数组概念。

6. sub
使用s u b发现并替换模式的第一次出现位置。字符串S T R包含‘poped popo pill’,执行下列s u b命令s u b(/ o p /," o p ",S T R)。模式o p第一次出现时,进行替换操作,返回结果如下:‘pO Ped pope pill’。

如:学生J . Tr o l l的记录有两个值一样,“目前级别分”与“最高级别分”。只改变第一个为2 9,第二个仍为2 4不动,操作命令为s u b(/ 2 6 /," 2 9 ",$ 0),只替换第一个出现2 4的位置。注意J . Tr o l l记录需存在。
代码:
[root@Linux_chenwy sam]# awk '$1=="J.Troll" sub(/26/,"29",$0)' grade.txt
M.Tans 5/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 29
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 29 26
L.Tansl 05/99 4712 Brown-2 12 30 28


7. substr
s u b s t r是一个很有用的函数。它按照起始位置及长度返回字符串的一部分。例子如下:
代码:
[root@Linux_chenwy sam]# awk '$1=="L.Tansl" {print substr($1,1,3)}' grade.txt
L.T

上面例子中,指定在域1的第一个字符开始,返回其前面5个字符。

如果给定长度值远大于字符串长度, a w k将从起始位置返回所有字符,要抽取L Ta n s l - e y的姓,只需从第3个字符开始返回长度为7。可以输入长度9 9,a w k返回结果相同。
代码:
[root@Linux_chenwy sam]# awk '$1=="L.Tansl" {print substr($1,1,99)}' grade.txt
L.Tansl


s u b s t r的另一种形式是返回字符串后缀或指定位置后面字符。这里需要给出指定字符串及其返回字串的起始位置。例如,从文本文件中抽取姓氏,需操作域1,并从第三个字符开始:
代码:
[root@Linux_chenwy sam]# awk '{print substr($1,3)}' grade.txt
Tans
Lulu
Bunny
Troll
Tansl


还有一个例子,在B E G I N部分定义字符串,在E N D部分返回从第t个字符开始抽取的子串。
代码:
[root@Linux_chenwy sam]# awk 'BEGIN{STR="A FEW GOOD MEN"}END{print substr(STR,7)}' grade.txt
GOOD MEN


8. 从s h e l l中向a w k传入字符串
a w k脚本大多只有一行,其中很少是字符串表示的。大多要求在一行内完成a w k脚本,这一点通过将变量传入a w k命令行会变得很容易。现就其基本原理讲
述一些例子。
使用管道将字符串s t a n d - b y传入a w k,返回其长度。
代码:
[root@Linux_chenwy sam]# echo "Stand-by" | awk '{print length($0)}'
8


设置文件名为一变量,管道输出到a w k,返回不带扩展名的文件名。
代码:
[root@Linux_chenwy sam]# STR="mydoc.txt"
[root@Linux_chenwy sam]# echo $STR|awk '{print substr($STR,1,5)}'
mydoc


设置文件名为一变量,管道输出到a w k,只返回其扩展名。
代码:
[root@Linux_chenwy sam]# STR="mydoc.txt"
[root@Linux_chenwy sam]# echo $STR|awk '{print substr($STR,7)}'
txt


阅读(838) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~