awk 命令使用指南

一:awk 的执行流程

(1) 首先执行BEGIN{} 块中的初始化操作
(2) 然后从指定的数据文件中循环读取一个数据行 ( 自动更新 NF、NR、$0、$1....., 等内建变量的值)
(3) 最后执行END {} 区块中的后续处理操作

二: awk 的选项
-F ":" 指定每个字段的分隔符
-v var=value 自定义变量

三: awk 的基本使用

  1. 输出命令

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)自定义变量
定义方法

  1. -v var=value
  2. BEGIN{var=value}

(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

  1. PATTERN (模式)
    (1). empty: 空模式,匹配每一行
    (2)./regular expression/: 仅能够被此处的模式匹配到的行
    awk '/^UUID/{print $1}' /etc/fstab

(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开始编号

猜你喜欢

转载自www.cnblogs.com/bingguoguo/p/10994649.html