一:awk 的执行流程
(1) 首先执行BEGIN{} 块中的初始化操作
(2) 然后从指定的数据文件中循环读取一个数据行 ( 自动更新 NF、NR、$0、$1....., 等内建变量的值)
(3) 最后执行END {} 区块中的后续处理操作
二: awk 的选项
-F ":" 指定每个字段的分隔符
-v var=value 自定义变量
三: awk 的基本使用
print item1,item2
要点: (1) , 号 做为分隔符
(2)输出的 各item 可以是字符串,也可以是数值,当前记录的字段 、变量 或 awk 的表达式
例: head -4 /etc/fstab | awk ‘{print "hello", $1}‘
(3) 如果省略 item 。相当于 $0 ,打印整行内容
2 . 变量
(1) 内建变量
FS: 输入字段分隔符 等同于 -F 选项 默认为空白
OFS: 输出时的字段分隔符, 默认空白
RS: 输入时的行分割符, 默认为 \n
ORS: 输出时的行分隔符, 默认为 \n 例: awk -F ":" -v OFS=":" ‘{print $1,$2,$3}‘ /etc/passwd
NF: 当前处理的行的字段个数(列数)
注: $NF 打印最后一个字段
NR : 当前处理的行数
FNR: 各文件分别计数(行数)
FILENEME: awk 浏览的文件名
$0: 当前处理的行的整行内容
$n: 当前处理的第n 个字段 (第 n 列)
ARGC: 命令行参数的个数 例: awk ‘BEGIN{print ARGC}‘ /etc/fstab /etc/issuee
ARGV: 数组,保存的是命令行中所给定的各参数
awk的执行流程:
(1). 首先执行 BEGIN {} 区块中的初始化操作:
(2). 然后从指定的数据文件中循环读取一个数据行 { 自动更新 NF、NR、$0、$1...} 等内建变量的值)
并执行 ‘模式或条件{编辑指令}‘ :
(3). 最后执行END {} 区块中的后续处理操作
awk的选项
-F ":" : 指定每个字段的分隔符,默认为空格
-v var=value 自定义变量
1.输出命令
print item1,item2
要点:(1) 逗号分隔符
(2) 输出的各 item 可以是字符串,也可以是数值,当前记录的字段、变量或awk的表达式
head -5 /etc/fstab | awk ‘{print "hello," $1}‘
(3) 如果省略 item,相当于 $0,打印整行内容
2、变量
(1)内建变量
FS: 输入字段分隔符 等同于 -F 默认空白
OFS: 输出时的字段分隔符 默认空白
RS: 输入时的行分隔符,默认为 \n
ORS: 输出时的行分隔符,默认为 \n
awk -F ":" -v OFS=":" ‘{print $1,$2,$3 }‘ /etc/passwd
NF 当前处理的行的字段个数(列数)
注:$NF: 打印最后一个字段
NR 当前处理的行的序数(行数)
FNR: 各文件分别计数: 行数
FILENAME awk 浏览的文件名
$0 当前处理的行的整行内容
$n 当前处理的第 n 个字段(第n列)
ARGC: 命令行参数的个数
awk ‘BEGIN{print ARGC}‘ /etc/fstab /etc/issue
3
ARGV: 数组,保存的是命令行中所给定的各参数:
awk ‘BEGIN{print ARGV[0]}‘ /etc/fstab /etc/issue
awk
awk ‘BEGIN{print ARGV[1]}‘ /etc/fstab /etc/issue
/etc/fstab
awk ‘BEGIN{print ARGV[2]}‘ /etc/fstab /etc/issue
/etc/issue
(2)自定义变量
定义方法
(3)awk 使用 linux 变量
3.printf
格式化输出:printf format, item1,item2,...
(1)format 必须给出
(2) 不会自动换行,需要显式给出换行分隔符, \n-----
(3) format 中需要分别为后面的每个 item 指定一个格式化符号;
格式符
%c: 显示字符的 ASCII码
%d,%i 显示十进制整数
%e,%E 科学计数法数值显示
%f 显示为浮点数
%g,%G 以科学计数法或浮点形式显示数值
%s 显示字符串
%u 无符号整数
%% 显示%自身
例子
awk -F ":" ‘{printf "Username: %s\n", $1}‘ /etc/passwd
awk -F: ‘{printf "Username: %s, UID: %d\n",$1,$3}‘ /etc/passwd
修饰符
%3.1f
例子
awk -F: ‘{printf "Username: %10s, UID: %d\n",$1,$3}‘ /etc/passwd
默认右对齐
-: 左对齐
awk -F: ‘{printf "Username: %-10s, UID: %d\n",$1,$3}‘ /etc/passwd
+: 显示数值的符号
awk -F: ‘{printf "Username: %-10s, UID: %+d\n",$1,$3}‘ /etc/passwd
4 .操作符
(1)算法操作符
x+y, x-y, x*y, x/5, x^y, x%y
+x: 转换为数值
(2)赋值操作符
= += -= *= /= %= ^=
++ --
(3)比较操作符:
< 小于
<= 小于等于
== 等于
!= 不等于
= 大于等于
~ 匹配正则表达式
!~ 不匹配正则表达式
(4)模式匹配符
~ 匹配 !~ 不匹配
(5)逻辑操作符
&& || !
(6)函数调用
function_name(参数1,参数2)
(7)条件表达式
selector ? if-true-expression;if-false-expression
awk -F: ‘{$3>=500?usertype="Common User":usertype="Sysadmin or SysUser";printf "%15s:%-s\n",$1,usertype}‘ /etc/passwd
(3) releational expression 关系表达式,结果有真有假,为真才会被处理
awk -F: ‘$3>=500{print $1,$3}‘ /etc/passwd
awk -F: ‘$NF=="/bin/bash"{print $1,$NF}‘ /etc/passwd
awk -F: ‘$NF~/bash$/{print $1,$NF}‘ /etc/passwd
4.line ranges: 行范围
指明起始行,结束行
cat /etc/passwd | awk -F: ‘/^root/,/^sync/ {print $1}‘
真:结果为非 0 值, 非空字符串为真
6.BEGIN/END 模式
BEGIN{编辑指令} //开始处理第一行文本之前的操作
END { 编辑指令 } // 处理完最后一行文本之后的操作
内建函数
length() 获取字符串的长度
操作练习
练习文本
cat grade.txt
M.Tansley 05/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26
P.Bunny 02/99 48 Yellow 12 35 26
J.Troll 07/99 48 42 Brown-3 12 26 26
L.Tansley 05/99 47 12 Brown-2 12 30 28
此文件有7个字段
打印全文
awk ‘{print}‘ grade.txt
打印第一列和第七列
awk ‘{print $1,$7}‘ grade.txt
打印第2行到4行
awk ‘(NR>=2)&&(NR<=4){print}‘ grade.txt
打印第一行和第三行的内容
awk ‘NR==1||NR==3‘ grade.txt
在文件开头加表头
awk ‘BEGIN{print "date age\n-----"}{print}‘ grade.txt
在文件结尾加内容
awk ‘{print}END{print "BY linux"}‘ grade.txt
在输出到屏幕的同时输出到文件
awk ‘{print}END{print "BY linux"}‘ grade.txt | tee a.txt
判断整行是否匹配Brown,匹配则输出整行
awk ‘$0~/Brown/ {print $0}‘ grade.txt
判断第三列是否等于48,匹配则输出整行
awk ‘$3=="48" {print}‘ grade.txt
判断整行是否不匹配Brown,不匹配则输出整行
awk ‘$0!~/Brown/ {print $0}‘ grade.txt
判断第四列是否等于Brown-2, 不等于则输出整行
awk ‘$4!= "Brown-2" {print $0}‘ grade.txt
过滤文件中的Green 或 green
awk ‘/[Gg]reen/ {print $0}‘ grade.txt
判断一列 是前面三个任意字母 a 开头
awk ‘/[Gg]reen/{print $0}‘ grade.txt
判断整行匹配Yellow或者 Brown
awk ‘$0~/(Yellow|Brown)/{print $0}‘ grade.txt
过滤 P 开头的行
awk ‘$0~/Brown/ {print $0}‘ grade.txt
统计行数和列数
awk ‘END{print NR}‘ grade.txt
awk ‘END{print NF}‘ grade.txt
打印 /etc/passwd 文件的第一列和第七列
awk -F ":" ‘{print $1,$7}‘ /etc/passwd
awk ‘BEGIN{FS=":"}{print $1,$7}‘ /etc/passwd
输出所有奇数
awk ‘(NR%2)==1{print}‘ grade.txt
输出所有偶数
awk ‘(NR%2)==0{print}‘ grade.txt
统计当前所有系统用户的用户名、UID、GID、登录的shell,制成 windows系统中的EXCEL表格
$7可以用 $NF 代替(最后一列)
awk -F ":" ‘{print $1","$3","$4","$7}‘ /etc/passwd > user.csv
打印倒数第二列内容
awk -F ":" ‘{print $(NF-1)}‘ /etc/passwd
当内存使用超过 85%时报警(取整数)
[ $(free -m|awk ‘/cache:/ {print int($3/($3+$4)*100)}‘) -gt 85 ] && echo "内存 已使用超过85%"
awk 中 引用 shell 变量
name="zhangsan"
awk -v nm="$name" ‘BEGIN{print nm}‘
awk -v nm="abc" ‘BEGIN{print nm}‘
awk 条件判断语句
单分支格式
‘{if(表达式)命令1;命令2;....}‘
例子
awk ‘{if($6<$7)print $7 too high}‘ grade.txt
awk ‘{if($4~/Brown/) print $0}‘ grade.txt
awk ‘{if($1=="P.Bunny"&&$4=="Yellow ")pinrt $0}‘ grade.txt
awk ‘{if($1=="P.Bunny"||$4=="Yellow ")pinrt $0}‘ grade.txt
awk ‘{name=$1;belets=$4;if(belets~/Yellow/)print name}‘ grade.txt
awk ‘BEGIN{basefile="27"}{if($6<basefile)print $1}‘ grade.txt
if/else else if 语句 多重判断
‘{if(表达式)命令1;命令2;...;
else if(表达式){命令1;命令2;..;else 命令1,命令2;...}‘
例子
awk ‘{if($7==44)print $1;else if($7==28)print $2;else print $3}‘ grade.txt
awk ‘{if($7==44)print $2;else print $1}‘ grade.txt
循环
while 循环 for 循环 do 循环
while 语句
while(表达式){语句}
例子
变量的初始值为1,若 i 小于等于 NF(记录中域的个数),则执行打印语句,切 i 每次加1,直到 i>NF
awk ‘NR==1{i=1;while(i<=NF){print NF,$i;i++}}‘ grade.txt
awk ‘BEGIN{test=100;total=0;while(i<=test){total+=i;i++;}print total;}‘
for 循环
格式1
便利数组中的元素
for(变量 in 数组){语句}
awk ‘BEGIN{for(k in ENVIRON){print k"="ENVIRON[k];}}‘
格式2
for(变量;条件;表达式){语句}
awk ‘NR==1{for (i=1;i<=NF;i++)print NF,$i;}‘ grade.txt
awk ‘BEGIN{total=0;for(i=0;i<=100;i++){total+=i;} print total;}‘
break 当 break 语句用于 while 或 for 语句时,导致退出程序循环
continue 当 continue 语句用于whiler或for语句时,使程序循环移动到下一个迭代
next 能够导致读入下一个输入行,并返回到脚本的顶部。这可以避免对当前输入行执行其他的操作过程
exit 语句使主循环退出并将控制转交给END;如果END存在;不存在则退出执行
do-while循环(不管第一个条件是否为真,都先执行一次循环)
格式:
do
{语句}while(条件)
awk ‘BEGIN{ total=0; i=0; do { total+=i; i++; }while(i<=100) print total; }‘
数组
关联数组 array[数组元素]
(1) 可使用任意字符串,字符串要使用双引号
(2) 如果某数组元素事先不存在,在引用时, awk会自动创建此元素,并将其值初始化为 "空串"
若要判断数组中是否存在某元素, 要使用 "index in array" 格式进行
wekdays=[mon]="monday"
awk ‘BEGIN{wekdays["mon"]="Monday";wekdays["Tue"]="Tuesday";for (i in wekdays) {print wekdays[i]}}‘
i 变量会遍历 wekdays数组的每个索引
获取系统中 tcp的连接状态统计
netstat -tan | awk ‘/^tcp>/{state[$NF]++}END{for (i in state){print i,state[i]}}‘ |sort -rn
注:实际工作中 netstat 效率比较低,建议使用 ss命令
ss -antup | awk ‘/tcp>/{state[$2]++}END{for (i in state){print i,state[i]}}‘| sort -rn
ss -antup | awk ‘/udp>/{state[$2]++}END{for (i in state){print i,state[i]}}‘| sort -rn
统计访问IP的具体数量
cat /var/log/httpd/access_log | awk ‘{ip[$1]++}END{for (i in ip){print i;ip[i]}}‘
函数
1.内置函数
rand(): 返回0和1之间的随机数
同一个awk命令取到的数值都是相同的
字符串处理
lengeth([s]) 返回指定字符串的长度
sub(r,s,[t]): 以 r 表示的模式来查找t所表示的字符串中的匹配内容。并将匹配内容更换为s 所表示的内容
切片
split(s,a[,r]): 以 r为分隔符切割字符串s,并将切割后的结果保存至a所表示的数组中
awk的数组索引从1开始编号
原文:https://www.cnblogs.com/bingguoguo/p/10994649.html