BASH命令和SHELL脚本总结(4)AWK篇

@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<ARGC ; 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
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

上面的例子中OFS为什么没有生效呢,原因是OFS指的是输出字段分隔符,所以必须对字段进行操作时OFS才会起作用,正确的方法应该是:

echo 'aaa bbbccc 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

正如Tim大师所讲的,$1=$1这个action,是我们对awk撒的谎,目的就是为了使得OFS生效,除此之外,NF+=0也是常用的方法

 

@如何让awk匹配变量呢?@

PATTERNFILE=($(cat$1))
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

 

@从文件中读入数据@

while readLINE 

do 

  echo"LINE : $LINE" 

done <auto.sh

 

@内建函数-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);}'
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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值