天天看点

awk使用技巧

一些有用的awk统计命令:

1.取范围内的内容

echo "ddd#fk*ll" | awk -F'[#*]' '{print $2}'

结果:

fk

echo "ddd#fk*ll" | awk -F'[#*]' '{print $1}'

ddd

说明:

#*中间的部分为$2, $1为#前面的部分,$3为*后的部分

2. 匹配非空行

awk '/^[^$]/ {print $0}' test.txt 

//之间的为匹配项,可以使用正则表达式 [^$]表示空行,前面再加上^就是表示非空行,/^[^$]/就是匹配非空行的意思

比如文件tt内容如下:

% cat tt

1

2

3

4

cat tt|awk '/^[^$]/ {print;}'

3. 匹配不是以zhuo开始的行

awk '/^[^zhuo]/ {print $0}' test.txt 

cat tt

2zhuo

zhuo

cat tt | awk '/^[^zhuo]/ {print;}'

4. 替换功能

echo "zhuo:x:503:504::/home/zhuo:/bin/bash" |awk 'gsub(/:/,"#") {print $0}'

zhuo#x#503#504##/home/zhuo#/bin/bash

把:替换为#

gsub(r,s) 在整个$0中用s替代r

gsub(r,s,t) 在整个t中用s替代r

5. 列最大值,最小值,求和等操作

you.txt文档内容

列求和: cat you.txt |awk '{a+=$1}END{print a}'

列求平均值:cat you.txt |awk '{a+=$1}END{print a/NR}'

列求最大值:cat you.txt |awk 'BEGIN{a=0}{if ($1>a) a=$1}END{print a}' 

求最小值:cat you.txt |awk 'BEGIN{a=11111111}{if ($1<a) a=$1}END{print a}' 

NR表示行数,是awk内置变量。

注意:在awk命令中, BEGIN 后面的{}中表示的,是在开始执行一次,而END后面的{}中表示的则是在最后执行一次。

6.一个应用例子,统计线程数目

cat tt | awk -F' ' '{if(($6==0)&&(and(strtonum("0x"$4) ,0x00380000) == 0x00000000)) print;}' | awk '{A = $13+0;if ((A<= 189217)) print;}' | awk '{A=substr($11, 37,17); print A}' | awk 'function rv(a){b=2; if(a=="f") b=4;if(a=="0"||a=="_") b=0;if(a=="1"||a=="2"||a=="4"||a=="8") b=1; if(a=="7"||a=="e"||a=="d"||a=="b")b=3; return b; } {a=0; for(i=1;i<=17;i++) { t=substr($1,i,1); b=rv(t);a+=b;} print $1,a}'|awk '{a+=$2} END {print a}'

tt内容为:

se0__SPI_SQ0_cmd 1 1 0000001a 00000_00000000_00000000 0 1 1 5 0 400000b0_00000020_c0041080_00900403_ffff4f4f_fff4f4ff @ 00124850

se0__SPI_SQ0_cmd 1 1 0000001a 00000_00000000_00000000 4 1 1 5 0 00000000_00000000_00000000_00000000_00000000_00000000 @ 00124854

se0__SPI_SQ0_cmd 1 1 0000001b 00000_00000000_00000000 0 3 1 5 0 400000b0_00000020_e0041080_00900403_ffffffff_ffffffff @ 00124860

结果为:

116

注意and函数和strtonum函数的用法

还有一个字符串处理函数substr以及在awk中自定义的函数rv。

7. 字符串分割

i com.sb3456.you t

dd you.are222.are me

cat tt | awk '{print $2}' | awk '{split($0, b, ".");print b[2]}'

sb3456

are222

cat tt | awk '{print $2}' | awk '{split($0, b, ".");print b[2]}'|cut -c 3-

3456

e222

在cut中 -c 3- 表示从第3个字符开始到最后一个字符, -c 3-4就是取第3个和第4个字符。

注意cut的另一个用法-d 后标表示用什么分隔,f2表示显示第二列:

echo "c,d,e,f,g" |cut -d "," -f2

结果为:d

8. awk 中的大小写转化函数

echo | awk '{ print toupper("test"), tolower("TEST") }'

TEST test

9.正则表达式中的使用

Fruit            Frice/lbs            Quantity

Banana           $0.89                100

Peach            $0.79                65

Kiwi             $1.50                22

Pineapple        $1.29                35

Apple            $0.99                78

cat tt | awk '  /\$[1-9][0-9]*\.[0-9][0-9]*/ {print $1,$2,$3;} /\$0\.[0-9][0-9]*/{prints ; }'

Kiwi $1.50 22

Pineapple $1.29 35

注意匹配项:第一个字符$接下来为1-9中的数字,然后在有任意个0-9的数字,然后再是.字符,再是0-9的数字是少一个。

10.两行打印在一行

文件 tt

12

14

17

18

cat tt3 | awk '{a= $1; getline; print a,$1}'

12 14

17 18

11. 计算两行的差

cat tt3 | awk 'NR > 1 { print $1 - last } { last = $1 }'

NR表示当前读取了多少行

12. 使用多个分隔符

awk 'BEGIN {FS="[,:%]"} {print $2, $3}' tt.txt

通过正则表达式的方式设定内置变量FS,可以把, : %都当作分隔符。

tt.txt

101,John Doe:CEO%10000

102,Jason Smith:IT Manager%5000

103,Raj Reddy:Sysadmin%4500

104,Anand Ram:Developer%4500

105,Jane Miller:Sales Manager%3000

上面awk执行的结果为:

John Doe CEO

Jason Smith IT Manager

Raj Reddy Sysadmin

Anand Ram Developer

Jane Miller Sales Manager

13. 使用输出分隔符

$ awk -F ',' 'BEGIN { OFS=":" } { print $2, $3 }' employee.txt

13. 使用行分隔符

默认的行分隔符应该是\n,我们可以用内置变量RS指定行分隔符

$ vi employee-one-line.txt

101,John Doe:102,Jason Smith:103,Raj Reddy:104,Anand Ram:105,Jane Miller

awk -F, 'BEGIN { RS=":" } { print $2 }' employee-one-line.txt

John Doe

Jason Smith

Raj Reddy

Anand Ram

Jane Miller

14. NF和$NF的含义

NF代表:浏览记录的域的个数

$NF代表:最后一个Field(列)

15. 进制的转化

十六进制转十进制:

echo '12af' | awk '{print

strtonum("0x"$0)}'

4783

十进制转十六进制:

echo "4783"|awk

'{printf("%x\n",$0)}'

12af

八进制转十进制:

echo '011257' | awk '{print strtonum($0)}'

十进制转八进制:

'{printf("%o\n",$0)}'

11257

16 位移操作

与   and(v1,v2)=v1&v2                     例 awk 'BEGIN{ s=and(5,4);print s}'

或   or(vl1,v2)=v1|v2                         例 awk 'BEGIN{ s=or(5,4);print

s}'

异或 xor(v1,v2)=v1^v2                      例 awk 'BEGIN{ s=xor(5,4);print

左移 lshift(val,count)=v<<count        例 awk 'BEGIN{

s=lshift(8,2);print s}'    

右移 rshift(val,count)=v>>count        例 awk

'BEGIN{ s=rshift(8,2);print s}