@AWK的格式@
注意一:BEGIN{写在同一行,END{写在同一行。
Awk-F"\t" 'BEGIN{ #BEGIN{必须写在一行,并且必须写在起始行。
}
$1==1&& $2==2 && $3==3{ #&&之间的空格可以省略
}
END{ #END{必须写在一行,
}'
'
注意二: AWK的管道只能被打开一次
BEGIN是初始化,在读文件之前进行,END是扫尾,在读文件之后进行。
@AWK的执行方式@
方式一 $ awk-f pay1.awk emp.dat
方式二 $ awk'{ print $2, $3 * $4 }' emp.dat
@AWK 的工作流程 @
执行 awk 时, 它会反复进行下列四步骤.
1. 自动从指定的数据文件中读取一个数据行.
2. 自动更新(Update)相关的内建变量之值. 如 : NF, NR,$0...
3. 依次执行程序中 所有 的 Pattern { Actions } 指令,其中Pattern { Actions } 的语法已涵盖这种 " if ( 条件) { 动作} "的架构。
4. 当执行完程序中所有 Pattern {Actions } 时, 若数据文件中还有未读取的数据, 则反复执行步骤1 到步骤4.
awk 会自动重复进行上述4 个步骤, 使用者不须于程序中编写这个循环 (Loop).
@内建变量@
$0,一字符串, 其内容为目前 awk 所读入的数据行.
$1,$0 上第一个字段的数据.
$2,$0 上第二个字段的数据.
$n,$0 上第n个字段的数据.
$NF (Numberof Fields) 为一整数, 其值表$0 上所存在的字段数目.
$NR (NumberofRecords)为一整数, 其值表awk 已读入的数据行数目.
$FILENAME
$FS 例如,FS ="[\t:]+" (改变字段分隔符,使它变为空格或者tab或者冒号。)
数组:使用字符串当数组的下标(index),类似关联数组使用数组前不须宣告数组名及其大小.
[例1]
例如 : awk 从资料文件 emp.dat 中读入第一笔数据行
"A125Jenny 100 210" 之后, 程序中:
$0 之值将是 "A125Jenny 100 210"
$1 之值为"A125"
$2 之值为"Jenny"
$3 之值为 100
$4 之值为 210
$NF 之值为 4
$NR 之值为 1
$FILENAME 之值为"emp.dat"
注意:在awk 中任何变量使用之前, 并不须事先声明. 其初始值为空字符串(Null string)或 0.
@读取命令行的参数@
建立文件如下, 命名为 see_arg :
#!/bin/sh
awk '
BEGIN {
for( i=0;i print ARGV[i]# 依次印出awk 所记录的参数 } ' $* 执行: $ ./see_argfirst-arg second-arg 结果: awk first-arg second-arg @实例之哈希应用@ 需求:分析apace日志,获取访问量较大的前十个IP地址 方法: awk‘{ips[$1]++;}END{for(ip in ips)print ip,ips[ip]}’ |sort –nk2|head -10 实例结果分析:该apace日志首列保存ip信息。能过awk对日志进行一次遍历,即实现了IP信息的获取,同时采用了哈希结构,对ip进行了累计。 @OFS为什么不起作用@ echo 'aaa bbbccc ddd 上面的例子中OFS为什么没有生效呢,原因是OFS指的是输出字段分隔符,所以必须对字段进行操作时OFS才会起作用,正确的方法应该是: echo 'aaa bbbccc ddd 正如Tim大师所讲的,$1=$1这个action,是我们对awk撒的谎,目的就是为了使得OFS生效,除此之外,NF+=0也是常用的方法 @如何让awk匹配变量呢?@ PATTERNFILE=($(cat$1)) @从文件中读入数据@ while readLINE do echo"LINE : $LINE" done @内建函数-index@ index( 原字串, 找寻的子字串 ) 若原字串中含有欲找寻的子字串,则返回该子字串在原字串中第一次出现的位置,若未曾出现该子字串则返回0. 执行 : $ awk 'BEGIN{print index("8-12-94","-") }' 结果:2 @内建函数-index@ length( 字串 ) : 返回该字串的长度 @内建函数-match@ match( 原字串, 用以找寻比对的正则表达式 ),awk 找到该字串后会依此字串为依据进行下列动作:设定awk 内建变量 RSTART,RLENGTH,并返回 RSTART 之值。 RSTART = 合条件的子字串在原字串中的位置. = 0 ; 若未找到合条件的子字串. RLENGTH = 合条件的子字串长度(贪婪匹配) = -1 ; 若未找到合条件的子字串. [例1] awk ' BEGIN { match("banana", /(an)+/ ) print RSTART,RLENGTH } ' 结果: 2 4 @内建函数-split@ split( 原字串, 数组名称, 分隔字符 ) awk 将依所指定的分隔字符(fieldseparator)来分隔原字串成一个个的栏位(field),并以指定的数组记录各个被分隔的栏位. [例1]: ArgLst ="5P12p89" split(ArgLst, Arr, /[Pp]/) 执行结果 : Arr[1]=5,Arr[2]=12, Arr[3]=89 sub( 比对用的正则表达式, 将替换的新字串, 原字串 ) [例1] A ="a6b12anan212.45an6a" sub(/(an)+[0-9]*/, "[&]", A) print A 结果输出 ab12[anan212].45an6a 总结:第二个参数"将替换的新字串"中可用"&"来代表"合於条件的子字串" [例2] awk ' BEGIN { data ="p12-P34 P56-p61" while( match(data ,/[0-9]+/) > 0) { printsubstr(data, RSTART, RLENGTH ) sub(/[0-9]+/,"",data) } }' 总结:通过 sub() 与 match() 的搭配使用,可逐次取出原字串中合乎指定条件的所有子字串. 结果输出 12 34 56 61 substr( 字串,起始位置 [,长度] ) [例1] $ awk 'BEGIN{ print substr("User:Wei-Lin Liu", 6)}' 结果印出 Wei-Lin Liu [例2]从文件的 Fullname 中分离出路径 与 档名 awk ' BEGIN{ Fullname ="/usr/local/bin/xdvi" match(Fullname, /.*\//) path = substr(Fullname,1, RLENGTH-1) name =substr(Fullname, RLENGTH+1) print"path :", path," name :",name } ' $* 结果印出 path :/usr/local/bin name : xdvi printf TIME=`date+%H" "%M|awk '{m=int($2/10)*10; printf("%02d%02d",$1,m)}'` 注意格式控制,printf("%02d%02d",$1,m)中的02d说明是2位数的整数。 @awk中的时间处理@ mktime( YYYYMM DD HH MM SS[ DST])生成时间 strftime([format[, timestamp]])格式化时间输出,将时间戳(从1970年1月1日开始到当前时间(不计闰年)的整秒数)转为时间字符串 [ixigua@SuSE ~]$ awk 'BEGIN{tstamp=mktime("2001 0101 12 12 12");print strftime("%c",tstamp);}'
aaa bbb ccc ddd
aaa bbb ccc ddd
aaa bbb ccc ddd' |awk -v OFS="|" '{print $0}'
aaa bbb ccc ddd
aaa bbb ccc ddd
aaa bbb ccc ddd
aaa bbb ccc ddd
aaa bbb ccc ddd
aaa bbb ccc ddd
aaa bbb ccc ddd' |awk -v OFS="|" '{$1=$1;print $0}'
aaa|bbb|ccc|ddd
aaa|bbb|ccc|ddd
aaa|bbb|ccc|ddd
aaa|bbb|ccc|ddd
iter3=0
while [ "$iter3" -lt ${#PATTERNFILE[@]} ]
do
PATTERN=${PATTERNFILE[$iter3]}
cat /admin/inputdata/*|awk -F"\t" -v pattern_awk=$PATTERN'$16~pattern_awk{print $16}'>>geturl.result.txt
echo"#############################################">>geturl.result.txt
iter3=$(($iter3+1))
done
2001年01月01日 星期一 12时12分12秒
[ixigua@SuSE ~]$ awk 'BEGIN{tstamp1=mktime("2001 01 01 12 1212");tstamp2=mktime("2001 02 01 0 0 0");print tstamp2-tstamp1;}'
2634468
[ixigua@SuSE ~]$ awk 'BEGIN{tstamp1=mktime("2001 01 01 12 1212");tstamp2=systime();print tstamp2-tstamp1;}'
308201392