awk介绍 awk是一种编程语言,主要用于在linux/unix下对文本和数据进行处理。 数据可以来自标准输入、一个或多个文件,或其它命令的输出。 awk的处理文本和数据的方式:逐行扫描文件,
awk介绍
awk是一种编程语言,主要用于在linux/unix下对文本和数据进行处理。
数据可以来自标准输入、一个或多个文件,或其它命令的输出。
awk的处理文本和数据的方式:逐行扫描文件,默认从第一行到最后一行,寻
找匹配的特定模式的行,并在这些行上进行你想要的操作。
awk使用方式
命令模式语法
awk 选项 'commands' 文件名常用选项
-v 定义变量并赋值-F 定义字段分割符号,默认的分隔符是空格
-F分隔符 或 -F"分隔符"
-F"[分隔符1分隔符2...]"
-F"[分隔符1分隔符2...]+" 压缩重复的分隔符
'命令部分(commands)'
引用shell变量需用双引号引起
通过 正则表达式,地址定位 去匹配特定模式的行进行列操作
'/root/{awk语句}' sed中: '/root/p''NR==1,NR==5{awk语句}' sed中: '1,5p'
'/^root/,/^ftp/{awk语句}' sed中:'/^root/,/^ftp/p'
{awk语句1;awk语句2;...}
'{print $0;print $1}' sed中:'p''NR==5{print $0}' sed中:'5p'
注:awk命令语句间用分号间隔
BEGIN...END....
'BEGIN{awk语句};{处理中};END{awk语句}''BEGIN{awk语句};{处理中}'
'{处理中};END{awk语句}'
脚本模式
脚本编写
#!/bin/awk -f 定义魔法字符以下是awk引号里的命令清单,不要用引号保护命令,一行一个命令,多个命令用分号间隔,命令的结尾只能是 \n
BEGIN{FS=":"}
NR==1,NR==3{print $1"\t"$NF}
...
脚本执行
方法1:awk 选项 -f awk的脚本文件 要处理的文本文件
awk -f awk.sh filename awk 无法修改源文件(shell语言)
同
sed -f sed.sh -i filename sed 可以修改源文件
方法2:
./awk的脚本文件(或者绝对路径) 要处理的文本文件
chmod +x awk.sh
./awk.sh filename
同
./sed.sh -i filename
awk内部相关变量
$0 当前处理行的所有记录(一整行)$1,$2...$n 文件中每行以间隔符号分割的不同字段(第n列) awk -F: '{print $1,$3}'
NF 当前记录的字段数(列数) awk -F: '{print NF}'
$NF 最后一列 $(NF-1)表示倒数第二列
FNR/NR 行号
FS 定义间隔符 'BEGIN{FS=":"};{print $1,$3}'
OFS 定义输出字段的分隔符,默认空格 'BEGIN{OFS="\t"};print $1,$3}'
RS 输入记录分割符,默认换行(awk认为的行的结束标志) 'BEGIN{RS="\t"};{print $0}'
ORS 输出记录分割符,默认换行 'BEGIN{ORS="\n\n"};{print $1,$3}'
FILENAME 当前输入的文件名
示例1
参考文件:[root@bobilinux tmp]# cat pass
ett:x:821:821::/home/ett:/bin/bash
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
user01:x:822:822::/home/user01:/bin/bash
user02:x:823:823::/home/user02:/bin/bash
user03:x:824:824::/home/user03:/bin/bash
user04:x:825:825::/home/user04:/bin/bash
user05:x:826:826::/home/user05:/bin/bash
yy1:x:827:827::/home/yy1:/bin/bash
# 打印用户名、用户家目录和默认shell
[root@bobilinux tmp]# awk -F: '{print $1,$(NF-1),$NF}' pass
ett /home/ett /bin/bash
rpc /var/lib/rpcbind /sbin/nologin
rpcuser /var/lib/nfs /sbin/nologin
nfsnobody /var/lib/nfs /sbin/nologin
user01 /home/user01 /bin/bash
user02 /home/user02 /bin/bash
user03 /home/user03 /bin/bash
user04 /home/user04 /bin/bash
user05 /home/user05 /bin/bash
yy1 /home/yy1 /bin/bash
# 打印列数
[root@bobilinux tmp]# awk -F: '{print NF}' pass #awk按行处理,每一行都打印列数
7
7
7
7
7
7
7
7
7
7
正则表达式(匹配行)
# 打印包含 ett 的行
[root@bobilinux tmp]# awk '/ett/{print $0}' pass
ett:x:821:821::/home/ett:/bin/bash
[root@bobilinux tmp]# awk '/ett/' pass
ett:x:821:821::/home/ett:/bin/bash
[root@bobilinux tmp]# awk '/ett/{print $1}' pass # 默认以空格分隔
ett:x:821:821::/home/ett:/bin/bash
# 打印包含 ett 的行的用户名和默认shell
[root@bobilinux tmp]# awk -F: '/ett/{print $1,$NF}' pass
ett /bin/bash
# 打印以 ett 开头的行到以 rpcuser 开头的行中的用户名和默认shell
[root@bobilinux tmp]# awk -F: '/^ett/,/^rpcuser/{print $1,$NF}' pass
ett /bin/bash
rpc /sbin/nologin
rpcuser /sbin/nologin
以上的输出结果默认以空格分隔,如果想指定输出结果的分隔符,在两列之间使用 "分隔符"
# 指定输出结果的分隔符
[root@bobilinux tmp]# awk -F: '/^ett/,/^rpcuser/{print $1" 的默认shell是 "$NF}' pass
ett 的默认shell是 /bin/bash
rpc 的默认shell是 /sbin/nologin
rpcuser 的默认shell是 /sbin/nologin
地址定位(定位行)
[root@bobilinux tmp]# awk 'NR==1,NR==5{print $0}' pass
ett:x:821:821::/home/ett:/bin/bash
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
user01:x:822:822::/home/user01:/bin/bash
# 地址定位+正则表达式
中间需要用分号隔开,否则语法错误
[root@bobilinux tmp]# awk 'NR==1,NR==5/^ett/{print $0}' pass
awk: NR==1,NR==5/^ett/{print $0}
awk: ^ syntax error
[root@bobilinux tmp]# awk 'NR==1,NR==5;/^ett/{print $0}' pass
ett:x:821:821::/home/ett:/bin/bash
ett:x:821:821::/home/ett:/bin/bash
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
user01:x:822:822::/home/user01:/bin/bash
示例2
分隔符可以在引号外面用-F指定,也可以在引号里面搭配BEGIN,用FS指定# 指定分隔符
[root@bobilinux tmp]# awk 'BEGIN{FS=":"};/^ett/,/^rpcuser/{print $1,$NF}' pass
ett /bin/bash
rpc /sbin/nologin
rpcuser /sbin/nologin
输出结果的分隔符可以在awk语句中用""指定,也可以在引号里面搭配BEGIN,用OFS指定
# 指定输出结果的分隔符
[root@bobilinux tmp]# awk -F: 'BEGIN{OFS="***********"};/^ett/,/^rpcuser/{print $1,$NF}' pass
ett***********/bin/bash
rpc***********/sbin/nologin
rpcuser***********/sbin/nologin
输入记录分割符,默认换行(awk执行过程中认为的行的结束标志)
[root@bobilinux tmp]# vim pass
ett:x:821:821::/home/ett:/bin/bash hello ^Iworld$
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin^Ite^Ist$
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin$
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin$
user01:x:822:822::/home/user01:/bin/bash$
user02:x:823:823::/home/user02:/bin/bash$
user03:x:824:824::/home/user03:/bin/bash$
user04:x:825:825::/home/user04:/bin/bash$
user05:x:826:826::/home/user05:/bin/bash$
yy1:x:827:827::/home/yy1:/bin/bash$
[root@bobilinux tmp]# awk '{print $0}' pass
ett:x:821:821::/home/ett:/bin/bash hello world
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin te st
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
user01:x:822:822::/home/user01:/bin/bash
user02:x:823:823::/home/user02:/bin/bash
user03:x:824:824::/home/user03:/bin/bash
user04:x:825:825::/home/user04:/bin/bash
user05:x:826:826::/home/user05:/bin/bash
yy1:x:827:827::/home/yy1:/bin/bash
[root@bobilinux tmp]# awk 'BEGIN{RS="\t"};{print $0}' pass
ett:x:821:821::/home/ett:/bin/bash hello
world
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
te
st
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
user01:x:822:822::/home/user01:/bin/bash
user02:x:823:823::/home/user02:/bin/bash
user03:x:824:824::/home/user03:/bin/bash
user04:x:825:825::/home/user04:/bin/bash
user05:x:826:826::/home/user05:/bin/bash
yy1:x:827:827::/home/yy1:/bin/bash
输出记录分割符,默认换行(awk处理的两次记录之间的分隔符)
[root@bobilinux tmp]# awk '{print $0}' pass
user02:x:823:823::/home/user02:/bin/bash
user03:x:824:824::/home/user03:/bin/bash
user04:x:825:825::/home/user04:/bin/bash
user05:x:826:826::/home/user05:/bin/bash
yy1:x:827:827::/home/yy1:/bin/bash
[root@bobilinux tmp]# awk 'BEGIN{ORS="*****"};{print $0}' pass
user02:x:823:823::/home/user02:/bin/bash*****user03:x:824:824::/home/user03:/bin/bash*****user04:x:825:825::/home/user04:/bin/bash*****user05:x:826:826::/home/user05:/bin/bash*****yy1:x:827:827::/home/yy1:/bin/bash*****[root@bobilinux tmp]# awk 'BEGIN{ORS="\n\n"};{print $0}' pass
user02:x:823:823::/home/user02:/bin/bash
user03:x:824:824::/home/user03:/bin/bash
user04:x:825:825::/home/user04:/bin/bash
user05:x:826:826::/home/user05:/bin/bash
yy1:x:827:827::/home/yy1:/bin/bash
[root@bobilinux tmp]#
示例3
当前输入的文件名[root@bobilinux tmp]# cat pass
user04:x:825:825::/home/user04:/bin/bash
user05:x:826:826::/home/user05:/bin/bash
yy1:x:827:827::/home/yy1:/bin/bash
[root@bobilinux tmp]# awk '{print FILENAME}' pass
pass
pass
pass
[root@bobilinux tmp]# cat pass
user04:x:825:825:@:/home/user04:@/bin/bash
user05:x:@826:826::/home/user05:/bin/bash
yy1:x:827:827@::/home/yy1:/bin/bash
[root@bobilinux tmp]#
[root@bobilinux tmp]# awk 'BEGIN{RS="@"};{print $0}' pass
user04:x:825:825:
:/home/user04:
/bin/bash
user05:x:
826:826::/home/user05:/bin/bash
yy1:x:827:827
::/home/yy1:/bin/bash
[root@bobilinux tmp]# awk 'BEGIN{RS="@";ORS="*"};{print $0}' pass
user04:x:825:825:*:/home/user04:*/bin/bash
user05:x:*826:826::/home/user05:/bin/bash
yy1:x:827:827*::/home/yy1:/bin/bash
*[root@bobilinux tmp]#
awk工作原理
awk -F: '{print $1,$3}' /etc/passwd
1、awk使用一行作为输入,并将这一行赋给内部变量$0,每一行也可称为一个记录,以换行符(RS)结束2、每行被间隔符:(默认为空格或制表符)分解成字段(或域),每个字段存储在已编号的变量中,从$1开始
问:awk如何知道用空格来分隔字段的呢?
答:因为有一个内部变量FS来确定字段分隔符。初始时,FS赋为空格
3、awk使用print函数打印字段,打印出来的字段会以空格分隔,因为$1,$3之间有一个逗号。逗号比较特殊,它映射为另一个内部变量,称为输出字段分隔符OFS,OFS默认为空格
4、awk处理完一行后,将从文件中获取另一行,并将其存储在$0中,覆盖原来的内容,然后将新的字符串分隔成字段并进行处理。该过程将持续到所有行处理完毕
awk变量定义
awk -v 变量名=变量值 '{awk语句}' 文件
awk -v 变量名=变量值 'BEGIN{awk语句}'
awk中调用定义的变量不需要加$[root@bobilinux tmp]# awk -v num=1 '{print num}' pass
1
1
1
[root@bobilinux tmp]# awk -v num=1 '{print $num}' pass
user04:x:825:825::/home/user04:/bin/bash
user05:x:826:826::/home/user05:/bin/bash
yy1:x:827:827::/home/yy1:/bin/bash
[root@bobilinux tmp]# awk -v num=1 'BEGIN{print num}'
1
[root@bobilinux tmp]# awk -v num=1 'BEGIN{print $num}'
[root@bobilinux tmp]#
awk中BEGIN...END使用
BEGIN:表示在程序开始前执行
END :表示所有文件处理完后执行
用法:'BEGIN{开始处理之前};{处理中};END{处理结束后}'
实例:
1、打印最后一列和倒数第二列(登录shell和家目录)
[root@bobilinux tmp]# awk -F: 'BEGIN{print "Login_shell\t\tLogin_home\n*************************************"};{print $NF"\t\t"$(NF-1)};END{print "*************************************"}' passLogin_shell Login_home
*************************************
/bin/bash /home/user02
/bin/bash /home/user03
/bin/bash /home/user04
/bin/bash /home/user05
/bin/bash /home/yy1
*************************************
[root@bobilinux tmp]# awk 'BEGIN{FS=":";print "Login_shell\t\tLogin_home\n*************************************"};{print $NF"\t\t"$(NF-1)};END{print "*************************************"}' pass
Login_shell Login_home
*************************************
/bin/bash /home/user02
/bin/bash /home/user03
/bin/bash /home/user04
/bin/bash /home/user05
/bin/bash /home/yy1
*************************************
2、打印/etc/passwd里的用户名、家目录及登录shell
[root@bobilinux tmp]# awk -F: 'BEGIN{OFS="\t";print "u_name\th_dir\tshell\n*********************************"};{print $1,$(NF-1),$NF};END{print "*********************************"}' passu_name h_dir shell
*********************************
user02 /home/user02 /bin/bash
user03 /home/user03 /bin/bash
user04 /home/user04 /bin/bash
user05 /home/user05 /bin/bash
yy1 /home/yy1 /bin/bash
*********************************
[root@bobilinux tmp]# awk -F: 'BEGIN{print "u_name\th_dir\tshell\n*********************************"};{printf "%-15s%-20s%-20s\n",$1,$(NF-1),$NF};END{print "*********************************"}' pass
u_name h_dir shell
*********************************
user02 /home/user02 /bin/bash
user03 /home/user03 /bin/bash
user04 /home/user04 /bin/bash
user05 /home/user05 /bin/bash
yy1 /home/yy1 /bin/bash
*********************************
awk格式化输出
print函数 类似echo
打印字符串 print "字符串"[root@bobilinux tmp]# date|awk '{print "Month: "$2"\nYear: "$NF}'
Month: May
Year: 2022
printf函数 类似echo -n
%d 数值类型%s 字符类型 strings
%-20s
占20字符
- 表示左对齐,默认是右对齐
printf 默认不会在行尾自动换行,加\n
printf "%s %s...\n",字符串1,字符串2...
{printf "%-15s %-20s %-20s\n",$1,$(NF-1),$NF}
[root@bobilinux tmp]# awk -F: '{printf "%-15s %-10s %-15s\n", $1,$2,$3}' pass
user04 x 825
user05 x @826
yy1 x 827
[root@bobilinux tmp]# awk -F: '{printf "|%15s| %10s| %15s|\n", $1,$2,$3}' pass
| user04| x| 825|
| user05| x| @826|
| yy1| x| 827|
[root@bobilinux tmp]# awk -F: '{printf "|%15s| %10s| %15s|", $1,$2,$3}' pass
| user04| x| 825|| user05| x| @826|| yy1| x| 827|[root@bobilinux tmp]#
awk和正则的综合运用
逻辑运算符== 等于
!= 不等于
> 大于
< 小于
> 大于等于
<= 小于等于
~ 匹配
!~ 不匹配
! 逻辑非
&& 逻辑与
|| 逻辑或
参考文件:
[root@bobilinux tmp]# cat passett:x:821:821::/home/ett:/bin/bash
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
user01:x:822:822::/home/user01:/bin/bash
user02:x:823:823::/home/user02:/bin/bash
user03:x:824:824::/home/user03:/bin/bash
user04:x:825:825::/home/user04:/bin/bash
user05:x:826:826::/home/user05:/bin/bash
yy1:x:827:827::/home/yy1:/bin/bash
实例
从第一行开始匹配到以nfs开头行[root@bobilinux tmp]# awk 'NR==1,/^nfs/{print $0}' pass
ett:x:821:821::/home/ett:/bin/bash
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
从第一行到第3行
[root@bobilinux tmp]# awk 'NR==1,NR==3{print $0}' pass
ett:x:821:821::/home/ett:/bin/bash
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
[root@bobilinux tmp]# awk 'NR>=1&&NR<=3{print $0}' pass
ett:x:821:821::/home/ett:/bin/bash
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
从以ett开头的行匹配到以nsf开头的行
[root@bobilinux tmp]# awk '/^ett/,/^nfs/{print $0}' pass
ett:x:821:821::/home/ett:/bin/bash
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
打印以ett开头或者以nsf开头的行
[root@bobilinux tmp]# awk '/^ett/||/^nfs/{print $0}' pass
ett:x:821:821::/home/ett:/bin/bash
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
[root@bobilinux tmp]# awk '/^ett|^nfs/{print $0}' pass
ett:x:821:821::/home/ett:/bin/bash
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
[root@bobilinux tmp]# awk '/^ett/;/^nfs/{print $0}' pass
ett:x:821:821
::/home/ett:/bin/bash
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
[root@bobilinux tmp]# grep -E '^ett|^nfs' pass
ett:x:821:821::/home/ett:/bin/bash
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
[root@bobilinux tmp]# sed -nr '/^ett|^nfs/p' pass
ett:x:821:821::/home/ett:/bin/bash
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
[root@bobilinux tmp]# sed -n '/^ett/p;/^nfs/p' pass
ett:x:821:821::/home/ett:/bin/bash
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
打印1-5行以bash结尾的内容:
[root@bobilinux tmp]# awk 'NR>=1 && NR<=5 && /bash$/' pass
ett:x:821:821::/home/ett:/bin/bash
user01:x:822:822::/home/user01:/bin/bash
理解;号和||的含义:
# 两个命令(条件)满足其一即可
[root@bobilinux tmp]# awk 'NR>=3 && NR<=6 || /bash$/' pass
ett:x:821:821::/home/ett:/bin/bash
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
user01:x:822:822::/home/user01:/bin/bash
user02:x:823:823::/home/user02:/bin/bash
user03:x:824:824::/home/user03:/bin/bash
user04:x:825:825::/home/user04:/bin/bash
user05:x:826:826::/home/user05:/bin/bash
yy1:x:827:827::/home/yy1:/bin/bash
# 两个独立的命令,都要执行匹配
[root@bobilinux tmp]# awk 'NR>=3 && NR<=6 ; /bash$/' pass
ett:x:821:821::/home/ett:/bin/bash
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
user01:x:822:822::/home/user01:/bin/bash
user01:x:822:822::/home/user01:/bin/bash
user02:x:823:823::/home/user02:/bin/bash
user02:x:823:823::/home/user02:/bin/bash
user03:x:824:824::/home/user03:/bin/bash
user04:x:825:825::/home/user04:/bin/bash
user05:x:826:826::/home/user05:/bin/bash
yy1:x:827:827::/home/yy1:/bin/bash
打印IP地址
[root@bobilinux tmp]# ifconfig eth0|awk '/inet addr/'|awk -F: '{print $2}'|awk '{print $1}'
192.168.192.131
[root@bobilinux tmp]# ifconfig eth0|awk -F"[: ]+" '/inet addr/{print $4}'
192.168.192.131
[root@bobilinux tmp]# ifconfig eth0|awk 'NR==2'|awk -F"[: ]+" '{print $4,$6,$8}'
192.168.192.131 192.168.192.255 255.255.255.0
[root@bobilinux tmp]# ifconfig eth0|awk 'NR==2'|awk -F"[: ]+" 'BEGIN{OFS="\n"};{print $4,$6,$8}'
192.168.192.131
192.168.192.255
255.255.255.0
awk的脚本编程
awk 选项 '正则,地址定位{awk语句}' 文件名
处理文件:'{语句}' 后面接文件
不处理文件:'BEGIN{语句}'
流程控制语句
if:
{if(表达式){语句1;语句2;...}}[root@bobilinux tmp]# awk -F: '{if($3==0) {print $1"是管理员"} }' /etc/passwd
root是管理员
[root@bobilinux tmp]# awk 'BEGIN{if($(id -u)==0) {print "root"}}'
root
if...else:
{if(表达式){语句;语句;...}else{语句;语句;...}}[root@bobilinux tmp]# awk -F: '{ if($3>=500 && $3 != 65534) {print $1"是普通用户"} else {print $1,"不是普通用户"}}' /etc/passwd
root 不是普通用户
bin 不是普通用户
user04是普通用户
user05是普通用户
yy1是普通用户
[root@bobilinux tmp]# awk 'BEGIN{if( $(id -u)>=500 && $(id -u) !=65534 ) {print "是普通用户"} else {print "不是普通用户"}}'
不是普通用户
if...else if...else:
{if(表达式1){语句;语句;...}else if(表达式2){语句;语句;...}else if(表达式3){语句;语句;...}else{语句;语句;...}}[root@bobilinux tmp]# awk -F: '{if($3==0){print $1,"是管理员"}else if($3>=1 && $3<=499 || $3==65534){print $1,"是系统用户"}else{print $1,"是普通用户"}}' /etc/passwd
root 是管理员
bin 是系统用户
daemon 是系统用户
user04 是普通用户
user05 是普通用户
yy1 是普通用户
[root@bobilinux tmp]# awk -F: '{ if($3==0) {i++} else if($3>=1 && $3<=499 || $3==65534 ) {j++} else {k++}};END{print "管理员个数为:"i "\n系统用户个数为:"j"\n普通用户的个数为:"k }' /etc/passwd
管理员个数为:1
系统用户个数为:27
普通用户的个数为:24
循环语句
while:
[root@bobilinux tmp]# i=1;while (($i <= 5));do echo $i;let i++;done1
2
3
4
5
[root@bobilinux tmp]# awk 'BEGIN{i=1;while(i<=5) {print i;i++}}'
1
2
3
4
5
文件里的每一行循环打印3次:
[root@bobilinux tmp]# awk -F: '{i=1;while(i<=3) {print $0;i++}}' pass
ett:x:821:821::/home/ett:/bin/bash
ett:x:821:821::/home/ett:/bin/bash
ett:x:821:821::/home/ett:/bin/bash
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
计算1-5的和:
[root@bobilinux tmp]# awk 'BEGIN { i=1;while(i<=5) {(sum+=i) i++};{print sum}}'
15
for:
[root@bobilinux tmp]# for((i=1;i<=5;i++));do echo $i;done1
2
3
4
5
[root@bobilinux tmp]# awk 'BEGIN{for(i=1;i<=5;i++) {print i}}'
1
2
3
4
5
文件里的每一行循环打印3次:
[root@bobilinux tmp]# awk -F: '{for(i=1;i<=3;i++) {print $0}}' pass
ett:x:821:821::/home/ett:/bin/bash
ett:x:821:821::/home/ett:/bin/bash
ett:x:821:821::/home/ett:/bin/bash
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
计算1-5的和:
[root@bobilinux tmp]# awk 'BEGIN{for(i=1;i<=5;i++) (sum+=i);{print sum}}'
15
[root@bobilinux tmp]# for ((i=1;i<=10;i+=2));do echo $i;done|awk -v sum=0 '{sum+=$0};END{print sum}'
25
嵌套循环:
#!/bin/bashfor ((y=1;y<=5;y++))
do
for ((x=1;x<=$y;x++))
do
echo -n $x
done
echo
done
1
12
123
1234
12345
[root@bobilinux tmp]# awk 'BEGIN{for(y=1;y<=5;y++) {for(x=1;x<=y;x++) {printf x};print}}'
1
12
123
1234
12345
[root@bobilinux tmp]# awk 'BEGIN{y=1;while(y<=5) {for(x=1;x<=y;x++) {printf x};print;y++}}'
1
12
123
1234
12345
循环的控制:
break 条件满足的时候中断循环continue 条件满足的时候跳过本次循环
[root@bobilinux tmp]# awk 'BEGIN{for(i=1;i<=5;i++) {if(i==3) break;print i} }'
1
2
[root@bobilinux tmp]# awk 'BEGIN{for(i=1;i<=5;i++){if(i==3) continue;print i}}'
1
2
4
5
[root@bobilinux tmp]# awk 'BEGIN{i=1;while(i<=5){if(i==3) break;print i;i++}}'
1
2
[root@bobilinux tmp]# awk 'BEGIN{i=0;while(i<5){i++;if(i==3) continue;print i}}'
1
2
4
5
awk算数运算
+ - * / %(模) ^(幂2^3)可以在模式中执行计算,awk都将按浮点数方式执行算术运算(shell中只能计算整数)
[root@bobilinux tmp]# awk 'BEGIN{print 1+1}'
2
[root@bobilinux tmp]# awk 'BEGIN{print 1+1.5}'
2.5
[root@bobilinux tmp]# awk 'BEGIN{print 1/1.5}'
0.666667
[root@bobilinux tmp]# awk 'BEGIN{print 1*1.5}'
1.5
[root@bobilinux tmp]# awk 'BEGIN{print 2**3}'
8
[root@bobilinux tmp]# awk 'BEGIN{print 2**1.5}'
2.82843
[root@bobilinux tmp]# awk 'BEGIN{print 2%1.5}'
0.5
awk统计案例
1. 统计/etc/passwd 中各种类型shell的数量[root@bobilinux tmp]# awk -F: '{shells[$NF]++};END{for (i in shells) {print i,shells[i]}}' /etc/passwd
/sbin/shutdown 1
/bin/bash 25
/sbin/nologin 24
/sbin/halt 1
/bin/sync 1
2. 网站访问状态统计 <当前时实状态 netstat>
# ss -an|grep 80|awk '{states[$1]++};END{for (i in states) {print i,states[i]}}'
TIME_WAIT 578
ESTABLISHED 1
LISTEN 1
# ss -an|grep 80|awk '{states[$1]++};END{for (i in states) {print i,states[i]}}'|sort -k2 -rn
TIME-WAIT 18
ESTAB 8
LISTEN 1
3. 统计当前访问的每个IP的数量 <当前时实状态 netstat,ss>
# netstat -ant |grep :80 |awk -F: '{ip_count[$8]++};END{for (i in ip_count) {print i,ip_count[i]}}'|sort
4. 统计Apache/Nginx日志中某一天的PV量 <统计日志>
# grep '27/Jul/2017' mysqladmin.cc-access_log |wc -l
14519
5. 统计Apache/Nginx日志中某一天不同IP的访问量 <统计日志>
# grep '27/Jul/2017' mysqladmin.cc-access_log|awk '{ips[$1]++};END{for (i in ips) {print i,ips[i]}}' |sort -k2 -rn |head
名词引入:
名词:VV = Visit View(访问次数)
说明:从访客来到您网站到最终关闭网站的所有页面离开,计为1次访问。若访客连续30分钟没有新开和刷新页面,或者访客关闭了浏览器,则被计算为本次访问结束。
独立访客(UV)
名词:UV= Unique Visitor(独立访客数)
说明:1天内相同的访客多次访问您的网站只计算1个UV。
网站浏览量(PV)
名词:PV=PageView (网站浏览量)
说明:指页面的浏览次数,用以衡量网站用户访问的网页数量。多次打开同一页面则浏览量累计。用户每打开一个页面便记录1次PV。
独立IP(IP)
名词:IP=独立IP数
说明:指1天内使用不同IP地址的用户访问网站的数量。同一IP无论访问了几个页面,独立IP数均为1