awk是按照流来处理的,所以处理1-5G的文本数据相对还是可以的!
求和
awk -F : -v sum=0 '{sum+=$3} END{print sum}' /etc/passwd
或者
awk -F : '{sum+=$3} END{print sum}' /etc/passwd
默认变量为0
规定日志格式
$17 为domainname
$19 为request
$21 为响应状态码
应用1: 匹配统计F5日志中,含有某个域名的数量
可以按照以下方法来套
1
2
|
[root@CentOS-6-121 scripts]
# awk -F: '$1=="root" {print $0}' /etc/passwd | wc -l
1
|
对以上进行改版,因为统计的时候利用了wc -l 进行了,现在不需要wc -l ,awk完成统计
1
2
|
[root@CentOS-6-121 scripts]
# awk -F: -v n=0 '{if($1=="root") n++;} END{print n}' /etc/passwd
1
|
-v 可以指定变量,在 awk ''中利用变量的时候直接使用,不需要"$n" 这个地方要区别shell
注意: 以下语句,默认不指定n变量的时候,虽然可以出结果,是因为在n++的时候会默认设置n为0,但是这样会出现bug,当没有匹配的时候,去大于n的时候就不是0而是空
1
2
|
[root@CentOS-6-121 scripts]
# awk -F: '{if($1=="root") n++;} END{print n}' /etc/passwd
1
|
bug:
1
2
3
|
[root@CentOS-6-121 scripts]
# awk -F: '{if($1=="rooot") n++;} END{print n}' /etc/passwd
[root@CentOS-6-121 scripts]
#
|
应用2: 使用shell中的变量和定义多变量 和逻辑运算符
&& 逻辑与
|| 逻辑或
! 否
~ 匹配字符串 !~ 不匹配后面更正则表达式
-v key1=value1 -v key2-values
引用变量两种方式
1
name="John"
-v myname=$name '{print myname}'
2 在awk中我们可以通过“’$变量名’”的方式读取sell scrpit程序中的变量。
name="John"
awk '{print 1,2,"'$name'"}' flil
原型:
awk -v t=0 -v domain="domain"−vrequest="/main/detail"−vcode=500′17==domain && 19 ~ request &&21 ==code {t++} END{print t}' access.log
0
测试语句:
与
1
2
|
[root@CentOS-6-121 scripts]
# awk -F: '$1=="root" && $3==0 {print $0}' /etc/passwd
root:x:0:0:root:
/root
:
/bin/bash
|
或
awk -F: '1=="root"||1=="nobody" {print 1"\t"3}' /etc/passwd
nobody-2
root0
非
awk -F: 'NF != "/bin/bash" {print1 "\t" $NF}' /etc/passwd
匹配:
awk 'NF !~ "/sbin/no*" {print1" " $3}' /etc/passwd
或
awk 'NF !~ /sbin\/no*/ {print1" " $3}' /etc/passwd (使用 ~ /express/ 是man awk 中正规的写法)
注意:
判断匹配的方法:
1)$n~正则表达式
2)if($n~正则表示式) print $
如果你的awk中使用了 BEGIN语句,就一定要使用 if 不能使用模式匹配,否则报错
如:
报错:
1
|
[root@CentOS-6-121 scripts]
# awk -F: '$1=="root" && $3==0 BEGIN{n=0} {n++} END{print n}' /etc/passwd
|
awk: 1=="root" &&3==0 BEGIN{n=0} {t++} END{print t}
awk: ^ syntax error
改为:
1
2
3
4
5
6
7
|
[root@CentOS-6-121 scripts]
# awk -F: 'BEGIN{n=0} {if($1 =="root" && $3==0)n++} END{print n}' /etc/passwd
1
使用变量:
[root@master ~]
# n=1000
[root@master ~]
# awk -v n=$n -F: '$3==n {print $1" "$3}' /etc/passwd
elasticsearch 1000
|
应用3: awk中的数组
1
|
awk
-F :
'{bash_array[$NF]++} END {for(i in bash_array) {print i,bash_array[i]}}'
/etc/passwd
|
/bin/nologin 1
/sbin/shutdown 1
/bin/false 1
/bin/bash 11
/sbin/nologin 28
/sbin/halt 1
/bin/sync 1
3 指定域名的
1
2
|
[root@shnh-bak001 f5-log]$
awk
'$17 ==
"gold.dianpingfang.com"
{++domain[$21]} END {
for
(k
in
domain) print k,domain[k]}' access.log
|
2
200 4498
301 2
500 15
302 321
304 2
应用四:统计目录下的一部分目录的数据大小
1
|
du
-s stu* |
awk
'{sum=sum+$1} END{print sum}'
|
数据库的连接情况
1
|
netstat
-tanp |
awk
'/3306/ {print $5}'
|
awk
-F
":"
'{a[$1]++}END{for (i in a) print a[i],i}'
|
sort
-nr
|
应用五:行范围指定
AWK 的匹配模式种类:
Patterns
AWK patterns may be one of the following:
BEGIN
END
/regular expression/
relational expression
pattern && pattern
pattern || pattern
pattern ? pattern : pattern
(pattern)
! pattern
pattern1, pattern2
awk -F : '{print NF":"2":"3":"4":"5":"6":"$1 > "/tmp/oldboy/passwd"}' /tmp/oldboy/passwd
打印第2、3、4、5行
sed -n "2,5p" /etc/passwd
awk "NR==2,NR==5" /etc/passwd
awk "NR>1&&NR<6" /etc/passwd
cat /etc/passwd | head -5 | tail -4
实例:
awk -F: 'NR==2,NR==5 {print $1}' /etc/passwd
awk -F: 'NR>1 && NR<6{print $1}' /etc/passwd
案例6: 打印awk第一次匹配到的关键字,之后的所有行!
分两步,第一找出第一次匹配的行,匹配nobody账号
1
|
awk
-F
":"
'{if($1 ~ "nobody") print NR;}'
passwd
|
15
25
思考,如何只匹配到一次后,就退出awk继续向下匹配而直接退出查找。
改良:
1
|
awk
-F
":"
'{if($1== "nobody") {print NR; exit 0}}'
passwd
|
15
第二: 打印第15行之后的所有行
1
|
awk
-F
":"
'{if(NR > 15) print $0;}'
passwd
|
或者(以下行范围更适用)
awk -F: 'NR>15{print $1}' /etc/passwd
可以提高难道综合成一条awk语句
1
|
awk
-F
":"
'{if($1== "nobody") {a=NR}} {if(NR>a && a!=0) print $0}'
passwd
|
为什么要做一个a!=0 的条件,因为没有匹配到nobody的时候,未定义赋值过的变量再awk中默认值为0。
案例七: awk中调用系统命令
1
|
awk
-F
":"
'{if($1== "nobody") {system("echo this is noboy user")}} '
passwd
|
或者: $1=="root" 字符串一定要用引号引起来,不然在awk里面就是变量拉
awk -F ":" '$1=="root" {system("echo this is noboy user")} ' /etc/passwd
案例7: awk多分隔符切,分隔符为[
rabbitmq的集群状态 partitions行 {partitions,[]}] 如果[] 中有内容i表示集群不正常。
1
|
if
[
"x"
!=
"x$(sudo /usr/sbin/rabbitmqctl cluster_status |grep partitions |awk -F '[\\[\\]]' '{print $2}')"
];
then
echo
0;
else
echo
1;
fi
|
案例8: 统计nf(iptables 跟踪链表中 各协议的数量)
1
|
awk
'{a[$3]++ } END{for (k in a) print k,a[k]}'
/proc/net/nf_conntrack
|
tcp 11
udp 26
icmp 1
案例7. 使用split内置函数进行分割
1
2
3
4
5
6
7
8
|
tac haproxy.log |
awk
'{
split
($6,a,
":"
)
if
(a[1]~
"05/Mar/2017"
){
print $0
}
if
(a[1]~
"04/Mar/2017"
){
exit
}
}' >> .
/a_access
.log
exit
|
案例8: 打印匹配的行并 输出文件名
awk '/root/{print FILENAME "-----"$0}' /etc/passwd
#FILENAME 是默认变量,或者使用grep实现
grep -H root /etc/passwd
#-H 是显示文件名在匹配的行前面
内置函数的使用
split的用法:
一、split 初始化和类型强制
awk的内建函数split允许你把一个字符串分隔为单词并存储在数组中。你可以自己定义域分隔符或者使用现在FS(域分隔符)的值。
格式:
split (string, array, field separator)
split (string, array) -->如果第三个参数没有提供,awk就默认使用当前FS值。
例2:计算指定范围内的和(计算每个人1月份的工资之和)
1
2
3
4
5
6
7
8
9
10
|
[root
@test
~]
# cat test.txt
Tom
2012
-
12
-
11
car
53000
John
2013
-
01
-
13
bike
41000
vivi
2013
-
01
-
18
car
42800
Tom
2013
-
01
-
20
car
32500
John
2013
-
01
-
28
bike
63500
[root
@test
~]
# awk '{split($2,a,"-");if(a[2]==01){b[$1]+=$4}}END{for(i in b)print i,b[i]}' test.txt
vivi
2800
Tom2500
John4500
|
2. gsub的函数
替换正则表达式的内容
gsub(r, s [, t]) For each substring matching the regular expression r in the string t,sub-stitute the string s。
t字符串中匹配r正则的替换成s字符串。
r: 正则表达式
s:字符串
t,如果省略就是 $0.
awk '0 ~ /6.8/ {gsub("6.8", "6.6",0); print $0}' /etc/issue
将最后一行为nologin的替换成 /bin/bash
awk -F: '{gsub(".*nologin","/bin/bash",NF);printNF}' /etc/passwd
3. length()函数
length([s])
返回字符串的长度,如果s没有提供,默认是$0。
[root@cuizhiliang ~]# cat /etc/issue |awk '{print length($2)}'
7
2
0
#分析文本中每行的字符大小 找到很长的那一行
[root@cuizhiliang ~]# cat /etc/issue |awk '{print length()}'
26
18
0
4 文本处理 大小写转换函数 toupper(string), tolower(string)
awk -F: 'NR==1,NR==2{print toupper($NF)}' /etc/passwd
/BIN/BASH
/SBIN/NOLOGIN
5 index函数
index(s, t)
返回t中的字符串出现在s中的开始位置.从1开始的位置。若没有则返回0 Returns the index of the string t in the string s, or 0 if t is not present. (This implies that character indices start at one.) [root@master ~]# awk 'BEGIN{print index("98765432123","23")}' 10 6 system 调用系统命令 重要的是调用系统给的命令的时候 参数适用awk的field字段。 head dfs.log | awk '{system("./purge_squid_url.sh " ""$0"")}' arp -n|awk '/^[1-9]/{system("echo "$1)}' arp -n| awk '/^[1-9]/{system("echo " ""$1"")}'
arp -n|awk '/^[1-9]/{system("arp -d "$1)}' |
cuizhiliang