awk提供了许多强大的字符串函数,见下表:
awk内置字符串函数
gsub(r,s) | 在整个$0中用s替代r |
gsub(r,s,t) | 在整个t中用s替代r |
index(s,t) | 返回s中字符串t的第一位置 |
length(s) | 返回s长度 |
match(s,r) | 测试s是否包含匹配r的字符串 |
split(s,a,fs) | 在fs上将s分成序列a |
sprint(fmt,exp) | 返回经fmt格式化后的exp |
sub(r,s) | 用$0中最左边最长的子串代替s |
substr(s,p) | 返回字符串s中从p开始的后缀部分 |
substr(s,p,n) | 返回字符串s中从p开始长度为n的后缀部分 |
详细说明一下各个函数的使用方法。
gsub函数有点类似于sed查找和替换。它允许替换一个字符串或字符为另一个字符串或字符,并以正则表达式的形式执行。第一个函数作用于记录$0,第二个gsub函数允许指定目标,然而,如果未指定目标,缺省为$0。
index(s,t)函数返回目标字符串s中查询字符串t的首位置。length函数返回字符串s字符
长度。match函数测试字符串s是否包含一个正则表达式r定义的匹配。split使用域分隔符fs将
字符串s划分为指定序列a。sprint函数类似于printf函数(以后涉及),返回基本输出格式fmt的
结果字符串exp。sub(r,s)函数将用s替代$0中最左边最长的子串,该子串被(r)匹配。
sub(s,p)返回字符串s在位置p后的后缀。substr(s,p,n)同上,并指定子串长度为n。
现在看一看awk中这些字符串函数的功能。
1.gsub
要在整个记录中替换一个字符串为另一个,使用正则表达式格式,/目标模式/,替换模式
/。例如改变学生序号4842到4899:
$ awk ‘gsub(’4842/, 4899) {print $0}’ grade.txt
J.Troll 07/99 4899 Brown-3 12 26 26
2.index
查询字符串s中t出现的第一位置。必须用双引号将字符串括起来。例如返回目标字符串
Bunny中ny出现的第一位置,即字符个数。
$ awk ‘BEGIN {print index(“Bunny”, “ny”)} grade.txt
4
3.length
返回所需字符串长度,例如检验字符串J.Troll返回名字及其长度,即人名构成的字符个
数。
$ awk ‘$1==”J.Troll” {print length($1) ” “$1}’ grade.txt
7 J.Troll
还有一种方法,这里字符串加双引号。
$ awk ‘BEGIN {print length(“A FEW GOOD MEN”)}’
14
4.match
match测试目标字符串是否包含查找字符的一部分。可以对查找部分使用正则表达式,返
回值为成功出现的字符排列数。如果未找到,返回0,第一个例子在ANCD中查找d。因其不
存在,所以返回0。第二个例子在ANCD中查找D。因其存在,所以返回ANCD中D出现的首位
置字符数。第三个例子在学生J.Lulu中查找u。
$ awk ‘{BEGIN {print match(“ANCD”, /d/)}’
$ awk ‘{BEGIN {print match(“ANCD”, /C/)}’
3
$ awk ‘$1==”J.Lulu” {print match($1, “u”)} grade.txt
4
5.split
使用split返回字符串数组元素个数。工作方式如下:如果有一字符串,包含一指定分隔
符-,例如AD2-KP9-JU2-LP-1,将之划分成一个数组。使用split,指定分隔符及数组名。此
例中,命令格式为(“AD2-KP9-JU2-LP-1″,parts_array,”-”),split然后返回数组下标数,这
里结果为4。
还有一个例子使用不同的分隔符。
$ awk ‘{BEGIN {print split(“123#456#678″, myarray, “#”)}’
3
这个例子中,split返回数组myarray的下标数。数组myarray取值如下:
Myarray[1]=”123″
Myarray[2]=”456″
Myarray[3]=”789″
6.sub
使用sub发现并替换模式的第一次出现位置。字符串STR包含‘popedpopopill’,执行下
列sub命令sub(/op/,”op”,STR)。模式op第一次出现时,进行替换操作,返回结果如下:
‘pOPedpopepill’。
假如grade.txt文件中,学生J.Troll的记录有两个值一样,“目前级别分”与“最高级别分”。只
改变第一个为29,第二个仍为24不动,操作命令为sub(/26/,”29″,$0),只替换第一个出现
24的位置。
$ awk ‘$1==”J.Troll” sub(/26/, “29″, $0)’ grade.txt
L.Troll 07/99 4842 Brown-3 12 29 26
L.Transley 05/99 4712 Brown-2 12 30 28
7.substr
substr是一个很有用的函数。它按照起始位置及长度返回字符串的一部分。例子如下:
$ awk ‘$1==”L.Transley” {print substr($1, 1,5)}’ grade.txt
L.Tan
上面例子中,指定在域1的第一个字符开始,返回其前面5个字符。
如果给定长度值远大于字符串长度, awk将从起始位置返回所有字符,要抽取L.Tansley的姓,只需从第3个字符开始返回长度为7。可以输入长度99,awk返回结果相同。
$ awk ‘{$1==”L.Transley” {print substr($1, 3,99)}’ grade.txt
Transley
substr的另一种形式是返回字符串后缀或指定位置后面字符。这里需要给出指定字符串及其返回字串的起始位置。例如,从文本文件中抽取姓氏,需操作域1,并从第三个字符开始:
$ awk ‘{print substr($1, 3)}’ grade.txt
Troll
Transley
还有一个例子,在BEGIN部分定义字符串,在END部分返回从第t个字符开始抽取的子串。
$ awk ‘{BEGIN STR=”A FEW GOOD MEN”} END {print substr(STR,7)) grade.txt
GOOD MEN
8.从shell中向awk传入字符串
awk脚本大多只有一行,其中很少是字符串表示的,这一点通过将变量传入awk命令行会变得很容易。现就其基本原理讲述一些例子。
使用管道将字符串stand-by传入awk,返回其长度。
$ echo “Stand-by” | awk ‘{print length($0)}’
8
设置文件名为一变量,管道输出到awk,返回不带扩展名的文件名。
$ STR=”mydoc.txt”
$ echo $STR | awk ‘{print subst($STR, 1, 5)}’
mydoc
设置文件名为一变量,管道输出到awk,只返回其扩展名。
$ STR=”mydoc.txt”
$ echo $STR | awk ‘{print substr($STR, 7)}’
txt
转载:http://hi.baidu.com/zzztou/blog/item/c09b9a31c5d65013ebc4af8c.html
http://www.ibm.com/developerworks/cn/linux/l-cn-awkinwork/index.html
##
awk读取多个文件
了解了FNR和NR这两个awk内置变量的意义就很容易知道这两种方法是如何运作的
FNR The input record number in the current input file. #已读入当前文件的记录数
NR The total number of input records seen so far. #已读入的总记录数
next Stop processing the current input record. The next input record is
read and processing starts over with the first pattern in the AWK
program. If the end of the input data is reached, the END block(s),
if any, are executed.
awk ‘NR==FNR{…}NR>FNR{…}’ file1 file2
# 读入file1的时候,已读入file1的记录数FNR一定等于awk已读入的总记录数NR,因为file1是awk读入的首个文件,故读入file1时执行前一个命令块{…}
# 读入file2的时候,已读入的总记录数NR一定>读入file2的记录数FNR,故读入file2时执行后一个命令块{…}
awk ‘NR==FNR{…;next}{…}’ file1 file2
# 读入file1时,满足NR==FNR,先执行前一个命令块,但因为其中有next命令,故后一个命令块{…}是不会执行的
# 读入file2时,不满足NR==FNR,前一个命令块{..}不会执行,只执行后一个命令块{…}
########################
# 处理 多个 文件
########################
当awk处理的文件超过两个时,显然上面那种方法就不适用了。因为读第3个文件或以上时,也满足NR>FNR (NR!=FNR),显然无法区分开来,所以就要用到更通用的方法了:
- ARGIND # 当前被处理参数标志
awk ‘ARGIND==1{…}ARGIND==2{…}ARGIND==3{…}… ‘ file1 file2 file3 …复制代码
- ARGV # 命令行参数数组
awk ‘FILENAME==ARGV[1]{…}FILENAME==ARGV[2]{…}FILENAME==ARGV[3]{…}…’ file1 file2 file3 …复制代码
- 把文件名直接加入判断
awk ‘FILENAME==”file1″{…}FILENAME==”file2″{…}FILENAME==”file3″{…}…’ file1 file2 file3 …复制代码
http://hi.baidu.com/beibeiboo/item/c0cb1856ba4344474eff20ab
awk -F, ‘BEGIN {
while ((getline < “file2″) > 0)
f2array[$2] = $1
OFS=”,”}{if (f2array[$1])
print f2array[$1],$2,$3,$4,$5
#else
# print $1 ” not listed in file2″ > “unmatched”
}’ file1