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;}'
1
2
3
4
3. 匹配不是以zhuo开始的行
awk '/^[^zhuo]/ {print $0}' test.txt
cat tt
1
2zhuo
zhuo
3
4
cat tt | awk '/^[^zhuo]/ {print;}'
1
2zhuo
3
4
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文档内容
1
2
3
4
列求和: 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. 字符串分割
cat tt
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.正则表达式中的使用
cat tt
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. 计算两行的差
文件 tt
12
14
17
18
cat tt3 | awk 'NR > 1 { print $1 - last } { last = $1 }'
结果:
2
3
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)}'
- 4783
十进制转八进制:
- echo "4783"|awk
'{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
s}'
左移 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}