awk是一个文本处理工具,通常用于处理数据并生成结果报告

awk语法

语法格式

  1. awk ‘BEGIN{}PATTERN{commands}END{}’ file_name
  2. stand out |awk ‘BEGIN{}PATTERN{commands}END{}’
  • BEGIN{} 正式处理数据之前执行
  • pattern 匹配模式
  • {commands} 处理命令,可能多行
  • END{} 处理完所有匹配数据后执行

awk内置变量

内置变量 含义
$0 整行内容
$1-$n 当前行的第1-n个字段
NF 当前行的字段个数,也就是有多少列
NR 当前的行的行号,从1开始计数
FNR 多文件处理时,每个文件行号单独计算,都是从0开始
FS 输入字段分隔符。不指定默认是空格或者tab键分割
RS 输入行分隔符。默认回车换行
OFS 输出字段分隔符。默认为空格
ORS 输出行分隔符。默认为回车换行
FILENAME 当前输入的文件名称
ARGC 当前命令行参数个数
ARGV 当前命令行参数数组
1awk '{print $0}'  awk.txt. #打印全部行
2awk 'BEGIN{FS=";"}{print $1}' awk.txt  # 分隔符为; 打印第一个字段,如果一行里没有;那么这行都为$1
3awk '{print NF}' awk.txt #每一行字段数
4awk '{print NR}' awk1.txt awk2.txt # 打印行号 累计计数 awk1.txt如果有2行那么awk2.txt是从行号3开始的
5awk '{print FNR}' awk1.txt awk2.txt # 打印行号 ,每个文件单独计数
 1cat awk.txt
 2#Hadoop|Spack|Flume--GO|JAVA|C++--|PHP|PYTHON|JAVASCRIPT
 3
 4awk 'BEGIN{RS="--"}{print $0}' awk.txt
 5#Hadoop|Spack|Flume
 6#GO|JAVA|C++
 7#|PHP|PYTHON|JAVASCRIPT
 8
 9awk 'BEGIN{RS="--";FS="|"}{print $3}' awk.txt
10#Flume
11#C++
12#PYTHON
13
14awk 'BEGIN{RS="--";FS="|";ORS="&";OFS=":"}{print $1,$3}' awk.txt
15#Hadoop:Flume&GO:C++&:PYTHON&
16
17
18awk  '{print FILENAME}' awk.txt #有几行打印几次 awk.txt
19awk  '{print ARGC}' awk.txt  # 2个参数 一个是awk命令 一个awk.txt
20awk  '{print ARGC}' awk.txt awk.txt #3个
21awk 'BEGIN{FS=":"}{print $NF}' /etc/passwd #与下面等价 NF=7 打印最后一列
22awk 'BEGIN{FS=":"}{print $7}' /etc/passwd

常用选项

选项 含义
-v 定义变量或引用变量
-f 指定awk 命令文件
-F 指定分隔符
-V 查看awk的版本号

格式化输出printf

格式符 含义
%s 打印字符串
%d 打印十进制数
%f 打印浮点数
%x 打印十六进制数
%o 打印八进制数
%e 打印数字的科学计数法形式
%c 打印单个自负的ASCII码
修饰符 含义
- 左对齐
+ 右对齐
# 8进制在前面加0,显示16进制在前面加0x
  1. 以字符串格式打印/etc/passwd的第7个字段,以":“作为分隔符
1   awk 'BEGIN{FS=":"} {printf "%s\n",$7}' /etc/passwd
  1. 以10进制格式打印/etc/passwd的第三个字段,以”:“作为分隔符
1  awk 'BEGIN{FS=":"} {printf "%d\n",$3}' /etc/passwd
  1. 以浮点数格式打印/etc/passwd的第三个字段,以”:“作为分隔符
1   awk 'BEGIN{FS=":"} {printf "%.2f\n",$3}' /etc/passwd

模式匹配

2种匹配模式

  • 正则匹配
  • 运算符匹配

正则匹配

匹配/etc/passwd中含有root的所有行

1awk 'BEGIN{FS=":"}/root/{print $0}' /etc/passwd

匹配/etc/passwd 以jenkins开始的所有行

1awk 'BEGIN{FS=":"}/jenkins/{print $0}' /etc/passwd

运算符匹配

关系运算符匹配

  • < 小于
  • > 大于
  • >= 大于等于
  • <= 小于等于
  • ~ 正则匹配
  • !~ 正则不匹配
  • == 等于
  • != 不等于

布尔运算符匹配

  • || 或
  • && 与
  • ! 非

以:分隔符,匹配/etc/passwd文件中第三个字段小于50的所有行信息

1awk 'BEGIN{FS=":"}$3<50{print $0}' /etc/passwd

以:分隔符,匹配/etc/passwd文件中shell是/bin/bash的所有行

1awk 'BEGIN{FS=":"}$7=="/bin/bash"{print $0}' /etc/passwd

以:分隔符,匹配/etc/passwd 用户id 是3位数字以上的 行

1awk 'BEGIN{FS=":"}$3~/[0-9]{3,}/{print $0}' /etc/passwd

匹配/etc/passwd 用户名是vagrant或是root

1awk 'BEGIN{FS=":"}$1=="root" || $1=="vagrant"{print $0}' /etc/passwd

表达式

运算符 含义
+
-
*
/
++x 在变量返回之前, x+1
x++ 在变量返回之后, x+1
** 或者 ^ 乘方
% 取模
1awk 'BEGIN{num1=20;num2=num1+30;print num1,num2}'
2#20 50
3awk 'BEGIN{num1=20;num2=num1+30;print num1+num2}' # 70
4awk 'BEGIN{num1=20;num2=num1+30;print num1-num2}' # -30
5awk 'BEGIN{num1=20;num2=num1+30;print num1*num2}' #1000
6awk 'BEGIN{num1=20;num2=num1+30;print num1**2}'  # 400
7awk 'BEGIN{num1=20;num2=num1+30;printf "%.2f",num1**2}'  # 400.00

计算空白行

1 awk '/^$/{sum++}END{print sum}' xx.sql
 1root@k8smaster:/home/maozhongyu1# cat xx.sql
 2mao 50 10 40
 3zhang 30 20 10
 4li 10 20 40
 5
 6
 7root@k8smaster:/home/maozhongyu1# awk 'BEGIN{printf "%-8s%-8s%-8s%-8s%s","name","yuwen","shuxue","yingyu","平均分\n";}{total=$2+$3+$4;avg=total/3; printf "%-8s%-8d%-8d%-8d%.2f\n",$1,$2,$3,$4,avg; }' xx.sql
 8name    yuwen   shuxue  yingyu  平均分
 9mao     50      10      40      33.33
10zhang   30      20      10      20.00
11li      10      20      40      23.33

动作中的条件

1root@k8smaster:/home/maozhongyu1# awk 'BEGIN{FS=":"} {if($3>1000) print $1}' /etc/passwd
2nobody
3maozhongyu
4maozhongyu1
5root@k8smaster:/home/maozhongyu1# awk 'BEGIN{FS=":"} {if($3>1000){print $1}}' /etc/passwd
6nobody
7maozhongyu
8maozhongyu1
 1root@k8smaster:/home/maozhongyu1# cat xx.sql
 2mao 50 10 40
 3zhang 30 20 10
 4li 10 20 40
 5root@k8smaster:/home/maozhongyu1# awk '{if($2>20) { print $1 }}' xx.sql
 6mao
 7zhang
 8
 9
10root@k8smaster:/home/maozhongyu1# awk '{if($2>40){printf "%s%s\n","大于40的用户",$1} else if($2<=40 && $2 >=25) {printf "%s%s\n","中规中矩",$1 }else {printf "%s%s\n","有点垃圾",$1}}' xx.sql
11大于40的用户mao
12中规中矩zhang
13有点垃圾li

动作中的循环

do while

1[vagrant@maozhongyu ~]$awk 'BEGIN{ total=0;i=1;do {total +=i;i++;} while(i<=100);print total}'
25050

while

1[vagrant@maozhongyu ~]$awk -v i=1 -v sum=0 'BEGIN{while(i<=100){sum+=i;i++};print sum}'
25050

for

1awk 'BEGIN{sum=0;for(i=1;i<=100;i++){sum+=i};print sum}'

字符串函数

函数名 解释 函数返回值
length(str) 计算字符串长度 整数长度值
index(str1,str2) 在str1中查找str2的位置 返回值为位置索引,从1计数
tolower(str) 转换为小写 转换后的小写字符串
topper(str) 转换为大写 转换后的大写字符串
substr(str,m,n) 从str的m个字符串开始,截取n位 截取后的字符串
split(str,arr,fs) 按fs切割字符串, 结果保存arr 切割后的子串的个数
match(str,RE) 在str中按照RE查找,返回位置 返回索引位置
sub(RE,replace,str) 在str中查找符合RE,替换为replace 只替换一个 替换的个数
gsub(RE,replace,str) 在str中查找符合RE,替换为replace 。替换全部 替换的个数

用户名长度

1$awk 'BEGIN{FS=":"} { printf "%d\n",length($1);}' /etc/passwd