AWK命令
awk是什么
awk属于一种脚本语言,由 GUN/Linux 自由软件资金会(FSF)进行开发和维护,通常也叫做 gawk(GNU AWK);用于在Linux平台或者Unix平台下对数据进行处理,数据可以来自标准输入(stdin)、一个或多个文件,或其它命令的输出。
awk和grep,sed命令不同点:grep,sed命令是对数据逐行处理,而awk可以对数据指定分割字符按列处理。此外:awk命令支持自定义变量,算数运行,字符串处理,循坏条件判断,数组以及函数等内置功能。
awk语法
awk 选项 '脚本代码' 文件
选项:
-F 分隔符 如 -F: -F[:.-] 默认为空格
-v 变量 如:-v a=10
-f 脚本文件
脚本代码:
模式:{处理动作}
正则匹配模式(默认) 匹配成功后执行处理动作
BEGIN模式 处理数据之前的前置操作
END模式 处理数据之后的后置操作
打印动作
print命令
打印多行文字
seq 10 | awk '{print "Hello"}'
打印指定列
$0代表整行
awk -F: '{print $0}' /etc/passwd
$1~n 代表第n列
awk -F: '{print $1$3}' /etc/passwd
,打印默认是空格
awk -F: '{print $1,$3}' /etc/passwd
可以设置打印格式
awk -F: '{print $1"---"$3}' /etc/passwd
支持\t制表位、\n换行
awk -F: '{print $1"\t"$3}' /etc/passwd
练习:获得磁盘利用率,截取文件系统和已用两列,去掉%
df | awk '{print $1,$5}' | tr -d %
df | awk '{print $1,$5}' | awk -F% '{print $1}'
printf命令
awk '{printf "格式字符串",$n,$m}'
格式字符串 = 格式符 + 修饰符
格式符 | 作用 |
---|---|
%c | 显示字符的ASCII码 |
%d %i | 显示十进制整数 |
%e %E | 以科学计数法显示 |
%f | 显示浮点数,即:小数 |
%s | 以字符串显示 |
%u | 显示无符号的整数 |
%% | 显示百分号% |
修饰符
m.n m控制显示的宽度(默认右对齐);
n对于小数表示小数点后精度, 如:%3.1f; 对于整数表示整数位数,不足则前面补0,如:%.3d
- 左对齐宽度, 如:%-15s
+ 显示数值的正负符号 如:%+d
案例:格式化输出用户名和uid
awk -F: '{printf "username:%-20s userid:%.3d\n",$1,$3}' /etc/passwd
练习:获得磁盘利用率,格式为
文件名:xxx 利用率:xxx
df | sed -n '2,$p'| awk '{printf "用户名:%-30s利用率:%d\n",$1,$5}'
变量
内置变量
内置变量 | 作用 |
---|---|
FS | 设置的分隔符 |
OFS | 输出时的分隔符,默认为空格 |
RS | 定义输入记录的分隔符,默认为换行符 |
ORS | 定义输出记录的分隔符,默认为换行符 |
NF | 按照FS分隔符分割了多少个字段 |
NR | 对每一条记录从1开始进行编号 |
FILENAME | 显示当前记录所在文件名 |
ARGC | 命令行参数的个数,在awk命令参数是指:awk命令本身和文件个数 |
ARGV[n] | ARGV数组存放了命令行各个参数,比如:取第一个参数 ARGV[0],取第二个参数 ARGV[1] |
FS变量
awk -F: '{print $1FS$3}' /etc/passwd
awk -v FS=":" '{print $1FS$3}' /etc/passwd
OFS变量
awk -v FS=":" -v OFS="---" '{print $1,$3}' /etc/passwd
user1---1001
user2---1002
test1---1003
RS变量
test.txt
aaa;bbb;ccc
ddd;eee;fff
awk -v RS=";" '{print $0}' test.txt
aaa
bbb
ccc
ORS变量
awk -v RS=";" -v ORS="..." '{print $0}' test.txt
aaa...bbb...ccc
ddd...eee...fff
ggg...mmm...nnn...
NF变量
打印列数
awk -v FS=":" '{print $1"列数:"NF}' /etc/passwd
打印最后一列
awk -v FS=":" '{print $1"最后列:"$NF}' /etc/passwd
NR变量
awk -F: '{print NR,$1}' /etc/passwd
awk -F: 'NR>=5&&NR<=10{print NR,$1}' /etc/passwd
FILENAME变量
awk -F: '{print $1,FILENAME}' /etc/passwd
ARGC变量
awk -F: '{printf "参数数量:%d,参数1:%s,参数2:%s,参数3:%s\n",ARGC,ARGV[0],ARGV[1],ARGV[$(ARGC-1)]}' /etc/passwd test.txt
练习:打印passwd倒数第二列
awk -v FS=":" '{print $1"倒数第二列:"$(NF-1)}' /etc/passwd
练习:打印passwd第10行
awk -F: 'NR==10{print NR,$1}' /etc/passwd
sed -n '10p' /etc/passwd
cat /etc/passwd | head -10 | tail -1
cat -n /etc/passwd | tr -d ' ' | grep '^10'
自定义变量
定义变量并输出
awk -v a=10 'BEGIN{print a}'
awk 'BEGIN{a=10;print a}'
变量结合文件处理
awk -F: '{title="用户";print $1,title}' /etc/passwd
awk -v age=20 -F: '{print $1,age}' /etc/passwd
awk -v age=20 -v title="用户" -F: '{print $1title,age"岁"}' /etc/passwd
awk -F: '{age=20;title="用户";print $1title,age"岁"}' /etc/passwd
运算符
算术运算
运算符 | 描述 |
---|---|
a + b | 相加运算 |
a - b | 相减运算 |
a * b | 相乘运算 |
a / b | 相除运算 |
a ^ b 或 a ** b | 次幂运算 |
a % b | 取模运算 |
a++ | 自增 |
a– | 自减 |
赋值运算
运算符 | 描述 |
---|---|
+= | 加法赋值运算,a += 1 相当于 a = a+1 |
-= | 减法赋值运算,a -= 1 相当于 a = a -1 |
*= | 乘法赋值运算 |
/= | 除法赋值运算 |
^= | 次幂赋值运算 |
%= | 取模赋值运算 |
比较运算
运算符 | 描述 |
---|---|
a == b | 判断a和b是否相等 |
a != b | 判断a和b是否不相等 |
a > b | 判断a是否大于b |
a >= b | 判断a是否大于等于b |
a < b | 判断a是否小于b |
a <= b | 判断a是否小于等于b |
练习:查看/etc/passwd
文件中uid大于1000的数据行
练习:打印文件中的奇数行
逻辑运算
运算符 | 描述 |
---|---|
&& | 逻辑与 |
|| | 逻辑或 |
! | 取反操作 |
练习:查看/etc/passwd
文件中uid 0到999的数据行
三目运算
根据条件判断,执行不同的操作
条件?操作1:操作2
awk模式
模式PATTERN:根据条件,过滤匹配的行,再做处理
空模式
空模式:不指定匹配正则信息,打印所有行
awk -F: '{print $1}' /etc/passwd
正则匹配模式
正则匹配模式:根据正则表达式匹配数据行,匹配到数据行进行处理,未能匹配到数据行不做任何处理
awk '/^UUID/' /etc/fstab
awk '$0 ~ /^UUID/' /etc/fstab
awk '! /^UUID/' /etc/fstab
awk '$0 !~ /^UUID/' /etc/fstab
表达式模式
表达式模式:只有表达式结果为真,则处理对应数据行,如果表达式结果为假,则不对数据行做任何处理
- 表达式为真:非0,非空字符串
- 表达式为假:数字0,或者是空字符串
seq 10 | awk '0'
seq 10 | awk '1'
seq 10 | awk '"aaa"'
seq 10 | awk '""'
示例
awk -F: '$3>=1000{print $1,$3}' /etc/passwd
awk -F: '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd
行模式
awk不支持直接用行号,但可以使用变量NR间接指定行号进行判断处理
seq 10 | awk 'NR>=3 && NR<=6'
awk 'NR>=3 && NR<=6{print NR,$0}' /etc/passwd
awk也支持sed命令的正则范围匹配,匹配一行信息到另一行信息进行处理,比如:匹配以bin开头的行到以sshd开头的行
sed -n '/^bin/,/^sshd/p' /etc/passwd
awk '/^bin/,/^sshd/' /etc/passwd
awk -F: '/^bin/,/^sshd/{print $1,$3}' /etc/passwd
BEGIN / END 模式
BEGIN模式:仅在开始处理文件中的文本之前执行一次
END模式:仅在文本处理完成之后执行一次
awk -F: 'BEGIN{print "用户","UUID","家目录"};{print $1,$3,$(NF-1)}'
/etc/passwd|column -t
awk -F: 'BEGIN{print "用户","UUID","家目录"};{print $1,$3,$(NF-1)};END{print "数据处理完毕!"}'/etc/passwd|column -t
示例:awk计算
awk 'BEGIN{print 10/3}'
awk -v var=10 'BEGIN{print var/3}
示例:统计/etc/service
文件中的空白行
[root@centos7 ~ ]# egrep "^$" /etc/services|wc -l
17
[root@centos7 ~ ]# awk '/^$/{i=i+1};END{print i}' /etc/services
17
示例:统计/etc/services文件中有井号开头的行
[root@centos7 ~ ]# egrep "^#" /etc/services|wc -l
102
[root@centos7 ~ ]# awk -v i=0 '/^#/{i=i+1};END{print i}' /etc/services
102
[root@centos7 ~ ]# awk '/^#/{i++};END{print i}' /etc/services
102
示例:统计系统中有多少个虚拟用户和普通用户
[root@centos7 ~ ]# awk -F: -v n=0 -v m=0 'BEGIN{printf "%-20s%-s\n","login_user","nologin_user"};/bash$/{n++};!/bash$/{m++};END{printf "%-20s%s\n",n,m}' /etc/passwd
login_user nologin_user
2 21