Linux awk命令详解-参数-选项-内置变量-内置函数-脚本(多图、多示例) ...

瑞星  金牌会员 | 2024-12-18 16:15:55 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 797|帖子 797|积分 2391

awk基础结构说明与示例

这个非常重要,只有理解了awk的基础结构,才能一眼看清awk在做什么,也便于记忆,不然过几天就忘了。
   awk [option] [BEGIN{}] ‘[pattern]{action}’ [END{}] file1 file2…
  awk是按行处置处罚指定文件的文本:

  • option是选项,可以设置分隔符等,可选
  • pattern是模式,匹配上才执行action,可选
  • action是动作,比方输出等
  • filename,表现要处置处罚的文件
  • BEGIN,awk开始之前执行1次
  • END,awk竣事之后执行1次

参数与内置变量


常用参数内置变量

符号变量说明-F字段分隔符,默认空格$0匹配到的当前行$nn为1、2、3…表现记载分隔之后第n个字段NFNumber of Field,awk当前处置处罚行的字段数,要取末了一个字段就是$NFNRNumber of Record,awk当前处置处罚的记载数(通常是行)FNRFile Number of Record,awk当前处置处罚的行在文件中的记载数(通常是行)FSField Separator,字段分隔符,默认空格RSRecord Separator,记载(通常是行)分隔符,默认换行符 其他参数内置变量

符号变量说明-f awk-script.awk指定awk脚本文件OFS输出字段的分隔符,默认空格,Output Field SeparatorORS输出行(记载)的分隔符,默认换行符,Output Record SeparatorFILENAME处置处罚的文件名称FIELDWIDTHS字段宽度-v k=v指定awk参数ARGCawk参数个数ARGVawk参数关联数组IGNORECASE是否忽略巨细写OFMT数字的输出格式,默认%.6g 简单示例理解option

我们先看一些简单的示例,来理解参数、变量
测试文件awk.txt
  1. aa bb cc 11 dd 22 aa
  2. bb cc aa
  3. 11 22 33
  4. luck boy
  5. 11 33 22
  6. 11:22:33
复制代码
简单参数

  1. # 使用$0,输出所有行
  2. awk '{print $0}' awk.txt
  3. # 使用空格做分隔符,输出第1个字段
  4. awk '{print $1}' awk.txt
  5. # 用:做分隔符,输出第1个字段
  6. awk -F : '{print $1}' awk.txt
  7. # 使用空格做分隔符,输出最后1个字段
  8. awk '{print $NF}' awk.txt
  9. # 使用空格做分隔符,输出每行字段总数
  10. awk '{print NF}' awk.txt
  11. # 打印第一个字段和最后一个字段释义---作为字段分隔符
  12. awk 'OFS="---" {print $1,$NF}' awk.txt
  13. # 释义ORS指定行分隔符
  14. awk 'ORS="行分隔符" {print $1,$NF}' awk.txt
复制代码

NR与FNR

NR和FNR主要区别表现在有多个文件的时候:

  • NR是awk处置处罚的当前总行数
  • FNR是awk处置处罚的当前行在文件中的行数
  1. awk '{print "文件:"FILENAME,"NR:",NR,"FNR:",FNR}' a1.txt a2.txt
复制代码

-v ARGC ARGV参数

  1. echo | awk -v v1="参数1" -v v2="v2" 'BEGIN{print v1,v2,ARGC;for( a in ARGV){print a,ARGV[a]}}'
复制代码

执行脚本

awk可以写非常复杂的命令,有时候写在1行之中不悦目,可以将命令写作文件中,然后像sed一样通过-f参数来执行脚本。
  1. awk -f awk-script.awk awk.txt
复制代码
  1. #!/bin/awk
  2. BEGIN {
  3.     print "脚本开始执行,设置选项"
  4.     FS=" "
  5.     RS="\n"
  6.     ORS="\n\n"
  7. }
  8. {
  9.     print $1","$NF
  10. }
  11. END{
  12.     print "脚本执行完成"
  13. }
复制代码

if else

  1. {
  2.     if ($1==11) {
  3.         print "匹配到11"
  4.     }
  5.     else if ($1=="luck") {
  6.         print "匹配到第1个字段luck"
  7.     }
  8.     else {
  9.         print "第一个字段为其他值"
  10.     }
  11. }
复制代码

for循环

for循环:
  1. {
  2.     for ( i=1;i<=5;i++ ) {
  3.         print "第",i,"次for循环"
  4.     }
  5. }
复制代码
关联数组

  1. BEGIN {
  2.     print "输出测试开始"
  3. }
  4. {
  5.     state["TIME-WAIT"]+=NF
  6.     state["LISTEN"]+=NF*2
  7. }
  8. END{
  9.     print "输出测试结束打印结果"
  10.     for( s in state) {
  11.         print state[s]
  12.     }
  13. }
复制代码
指定匹配pattern

  1. BEGIN {
  2.     print "输出测试开始"
  3. }
  4. /^11/{
  5.     state["TIME-WAIT"]+=NF
  6.     state["LISTEN"]+=NF*2
  7. }
  8. END{
  9.     print "输出测试结束打印结果"
  10.     for( s in state) {
  11.         print s":",state[s]
  12.     }
  13. }
复制代码

使用正则指定分隔符

比方,下面文件要怎样分割此中的数字呢?
  1. 11,22,,33,,,4,5
  2. 11,,,22,,33,,,4,5
  3. 11 22,, 33 ,,, 4, 5
复制代码
  1. # 使用正则[ ,]+作为分隔符
  2. awk -F '[ ,]+' '{print $1" "$NF}' split.txt
  3. # 使用1个或多个空白字符做分隔符
  4. awk -F [[:space:]+] '{print $1,$2}' sed.txt
  5. # 查看网卡eth0的ipv4、掩码、广播地址
  6. ifconfig eth0 | awk -F [" ":]+ 'NR==2{print "ip4:"$3,"掩码:"$5,"广播地址:"$7}'
复制代码
理解pattern

正则与逻辑

比较符号说明>小于<大于>=小于即是<=大于即是&&与~正则匹配(包罗)!~正则匹配(不包罗)
  1. # 使用空格做分隔符,匹配aa开头的行输出行号(匹配到新行的行号)
  2. awk '/^aa/{print NR}' awk.txt
  3. # 输出第2个字段大于第1个字段的行
  4. awk '$2 > $1{print $0}' awk.txt
  5. # 打印最后一个字段包含bo的行
  6. awk '$NF ~ /bo/{print $0}' awk.txt
  7. # 打印最后一个字段不包含bo的行
  8. awk '$NF !~ /bo/{print $0}' awk.txt
  9. # 打印字段数为3的行
  10. awk 'NR == 3{print $0}' awk.txt
  11. # 打印第1个字段是11或者bb的行,注意字符串类型加双引号
  12. awk '$1==11 || $1=="bb"{print $0}' awk.txt
  13. # 打印第1个字段是11并且第2个字段是22的行
  14. awk '$1==11 && $2==22{print $0}' awk.txt
  15. # 查看2到4行的第1个字段
  16. awk '{if(NR>=2 && NR<=5) print $1}' awk.txt
复制代码
算术

符号说明+加-减*乘/除%求余
  1. awk '$1 + $2 > 2{print $0}' awk.txt
  2. awk '$1 * $2 > 2{print $0}' awk.txt
  3. # 打印偶数行
  4. awk 'NR % 2 == 0{print $0}' awk.txt
  5. # 打印奇数行
  6. awk 'NR % 2 == 1{print $0}' awk.txt
复制代码
printf

格式符号说明%cASCII字符%d10进制整数,有符号%u10进制整数,无符号%e科学计数法%f浮点数%o八进制%c单字符%s字符串%x十六进制值%g自适应-左对齐修饰符#8进制加前缀0,16进制加前缀0x+显示使用d 、e 、f和g转换的整数时,加上正负号+或-0用0添补,默认空白字符,数字右对齐生效
  1. echo "888888 16 55" | awk '{printf("科学:%e\n8进制:%o\n8进制:%#o\n16进制:%x\n16进制:%#x\n",$1,$2,$2,$3,$3)}'
  2. # printf的换行要自己加
  3. awk '{printf("文件名:%10s,行号:%s,列数:%s,内容:%s\n",FILENAME,NR,NF,$0)}' awk.txt
  4. awk '{ print "第1个字段: " $1 "\t\t最后一个字段:" $NF }' awk.txt
  5. awk '{printf "%10s\n",$1}' awk.txt
  6. awk '{printf "%-10s\n",$1}' awk.txt
  7. awk '{printf "%010d\n",$1}' awk.txt
复制代码

if else for while

  1. # 语句用{}
  2. awk '{if($1>$2){print "大于"}else{print "小于或等于"}}' awk.txt
  3. # 打印所有字段
  4. awk '{for(i=1;i<=NF;i++){print $i}}' awk.txt
  5. awk '{i=1; while(i<NF){print $i;i++}}' awk.txt
  6. awk '{if(NR%2==0){print "-----"}print $0}' awk.txt
  7. # 输出文件2到5行
  8. awk '{if(NR>=2 && NR<=5) print $0}' awk.txt
复制代码
BEGIN END

注意是大写的BEGIN END
  1. # BEGIN最先执行,END最后执行
  2. awk 'BEGIN {print "执行begin语句"}  {print $1","$NF} END {print "执行end语句"}' awk.txt
  3. # 多条语句;分割
  4. awk 'BEGIN{num=0;a+=5;print a}'
  5. # 支持正则
  6. awk 'BEGIN{str="aa100bbcc";if(str~/100/) {print "字符串包含数字100"}}'
  7. # echo不能省略,因为awk默认需要文件,这里echo没有输入,使用begin中初始化的变量
  8. echo|awk 'BEGIN{str="bb100aaa"}str~/100/{print "字符串包含数字100"}END{print "end"}'
  9. # 支持三目运算符
  10. awk 'BEGIN{num=200;print num==200?"状态码正常":"状态码错误"}'
  11. # 可以通过FS变量来指定分隔符
  12. awk 'BEGIN{FS=":"}{print NF}' awk.txt
  13. awk 'BEGIN{FS=":";OFS="#"}{print $1,$2}' awk.txt
  14. # 统计第1个字段等于11的行数
  15. awk 'BEGIN {count=0;} {if($1==11){count=count+1};print $0} END{print "第1个字段是11行数:",count}' awk.txt
复制代码
next(跳过行)

next表现跳过行
  1. # 打印偶数行,跳过奇数行
  2. awk 'NR%2==1{next}{print NR,$0;}' awk.txt
  3. # 将11开头的行缓存拼接到后面行的前面
  4. awk '/^11/{cache=$0;next;}{print cache"####"$0;}' awk.txt
  5. # 只拼接到下1行
  6. awk '/^11/{cache=$0"####";next;}{print cache$0;cache=""}' awk.txt
复制代码

重定向输出到文件

  1. # 覆盖原文件
  2. echo | awk '{printf("hello word!\n啊哈\n") > "awk-data.txt"}'
  3. # 在原文件上追加内容
  4. echo | awk '{printf("hello word\n娘子\n") >> "awk-data.txt"}'
复制代码
字符串函数

更换函数

函数说明gsub(r,s)在整个$0中用s代替rgsub(r,s,t)在整个t中用s替代rsub(r,s)用$0中最左边最长的子串代替ssubstr(s,p)返回字符串s中从p开始的后缀部门substr(s,p,n)返回字符串s中从p开始长度为n的后缀部门 拆分与查找函数

函数说明index(s,t)返回s中字符串t的第1个位置,索引从1开始,如果没有找到返回0match(s,r)测试s是否包罗匹配r的字符串,返回第1个匹配位置,没有匹配则为0split(s,a,fs)在fs上将s分成序列asprint(fmt,exp)经fmt格式化后的exp 其他字符串函数

函数说明length(s)返回s字符长度blength(s)返回s字节长度tolower(s)转换为小写字母toupper(s)转换为大写字母 字符串函数示例

  1. # 打印长度和匹配aa的位置
  2. awk '{print length($0),match($0,"aa")}' awk.txt
  3. # 将aa替换为aa-aa
  4. awk '{gsub("aa","aa-aa");print $0}' awk.txt
  5. # 用[0-9]+在content匹配,并用####替换
  6. awk 'BEGIN{content="what are word 99 啊哈 100 娘子 88";gsub(/[0-9]+/,"####",content);print content}'
  7. # 索引位置从1开始
  8. awk 'BEGIN{content="what are word 99 啊哈 100 娘子 88";print index(content,"what")}'
  9. # 返回的是第1个位置
  10. awk 'BEGIN{content="what are word 99 啊哈 100 娘子 88";print index(content,"are")}'
  11. # 没找到返回0
  12. awk 'BEGIN{content="what are word 99 啊哈 100 娘子 88";print index(content,"where")}'
  13. # 索引位置从1开始
  14. awk 'BEGIN{content="what are word 99 啊哈 100 娘子 88";print match(content,"what")}'
  15. # 返回的是第1个位置
  16. awk 'BEGIN{content="what are word 99 啊哈 100 娘子 88";print match(content,"are")}'
  17. # 没找到返回0
  18. awk 'BEGIN{content="what are word 99 啊哈 100 娘子 88";print match(content,"where")}'
  19. # 从第5个字符开始,截取6个字符
  20. awk 'BEGIN{content="what are word 99 啊哈 100 娘子 88";print substr(content,5,6);}'
  21. # 用空格拆分content,然后打印数组长度和数组
  22. awk 'BEGIN{content="what are word 99 啊哈 100 娘子 88";split(content,resultArray," ");print length(resultArray);for(k in resultArray){print k,resultArray[k];}}'
  23. # 默认就是使用空格拆分,所以可以省略第3个参数
  24. awk 'BEGIN{content="what are word 99 啊哈 100 娘子 88";split(content,resultArray);print length(resultArray);for(k in resultArray){print k,resultArray[k];}}'
复制代码

算术函数

函数说明atan2(y,x)y/x的反正切cos(x)x的余弦;x 是弧度sin(x)x的正弦;x 是弧度exp(x)x幂函数log(x)x的自然对数sqrt(x)x平方根int(x)x取整rand()生成随机数n,0 <= n < 1
  1. awk 'BEGIN{srand();num=100*rand();print num}'
  2. awk 'BEGIN{srand();num=int(100*rand());print num}'
  3. awk 'BEGIN{srand();num=sqrt(16);print num}'
复制代码
其他函数

函数说明system()调用体系命令mktime()生成时间strftime()格式化时间输出,将时间戳转为时间字符串systime()得到时间戳,秒close()关闭流,通常和getline连合使用getline从尺度输入、重定向、管道、文件等输入流获取数据 体系调用(system)

awk中可以使用system()来调用体系命令
  1. # 创建第1个字段为文件名的txt文件
  2. awk '{system("touch "$1".txt")}' awk.txt
复制代码

用awk命令来执行文件中的所有awk命令:
  1. awk 'BEGIN{print "脚本命令执行开始"}/^awk/{print "执行命令:"$0;system($0)}END{print "\n脚本命令执行结束"}' awk-sh.txt
复制代码

时间与格式化(mktime systime strftime)

更符合中国习惯格式:
格式说明%Y4位年(2024)%y2位年(24)%m数字月份%d几号,03表现3号%e几号,3表现3号%H24小时,16表现下战书4点%M分钟%S秒%D月/日/年,11/03/24%y2位年(24) 西方格式习惯:
格式说明%c当地日期和时间,Wed 01 Jan 2025 11:59:59 PM CST%I12小时,04,可能是早上4点,也可能是下战书4点%p12小时表现法(AM/PM)%b月缩写(Nov)%B月(November)%j从1月1日起一年中的第几天%w星期几数字(星期天是0)%A星期几(Sunday)%U年中的第几个星期(星期天作为一个星期的开始)%W年中的第几个星期(星期一作为一个星期的开始)%x重新设置当地日期%X重新设置当地时间%Z时区%%百分号(%)
  1. # 打印当前时间戳,10位、秒
  2. awk 'BEGIN{now=systime();print now}'
  3. # 根据时间创建时间戳:年月日时分秒 yyyy MM dd HH mm ss
  4. awk 'BEGIN{time=mktime("2025 01 01 23 59 59");print time}'
  5. # 时间戳不好看,格式化一下
  6. awk 'BEGIN{time=mktime("2025 01 01 23 59 59");print strftime("%c",time)}'
  7. # 还不好看,在简化一下
  8. awk 'BEGIN{time=mktime("2025 01 01 23 59 59");print strftime("%D",time)}'
  9. # 还不好看,自定义一下
  10. awk 'BEGIN{time=systime();print strftime("%Y-%m-%d %H:%M:%S",time)}'
  11. # 计算一下到元旦还有多少天
  12. awk 'BEGIN{time1=mktime("2025 01 01 00 00 00");time2=systime();print int((time1-time2)/(24 * 3600))}'
复制代码

读取流数据,关闭流(getline close)

  1. awk 'BEGIN{ "date" | getline time; print time }'
  2. awk 'BEGIN{ "date" | getline time; split(time,times); for(t in times){print t,times[t]}}'
  3. # getline 没有参数默认赋值个$0,print没有变量,默认输出$0
  4. awk 'BEGIN{ while( "ls" | getline) print}'
  5. awk 'BEGIN{ while( "ls" | getline) print $0}'
  6. # NF也会被赋值,注意不能使用别名如ll
  7. awk 'BEGIN{ while( "ls -l" | getline) print NF,NR,FNR}'
  8. # 管道方式
  9. awk 'BEGIN{while("cat /home/ubuntu/awk.txt"|getline){print NF,NR,FNR};close("/home/ubuntu/awk.txt");}'
  10. # 重定向方式
  11. awk 'BEGIN{while(getline < "/home/ubuntu/awk.txt"){print NF,NR,FNR};close("/home/ubuntu/awk.txt");}'
  12. # 从标准输入获取
  13. awk 'BEGIN{print "标准输入值:";getline value;print value;}'
复制代码
实例

与ss、netstat连合使用,查看IP 端口

  1. # 当前tcp连接的打印ip端口
  2. netstat -an | awk '/tcp/{print $4}'
  3. # 只打印端口
  4. netstat -an | awk '/tcp/{print $4}' | awk -F: '{print $NF}'
  5. # 去重之前要先排序,因为uniq只去相邻重复的数据
  6. netstat -an | awk '/tcp/{print $4}' | awk -F: '{print $NF}' | sort -n | uniq
  7. # 打印本地监听的ip和端口
  8. ss -tunl | awk '/tcp/{print $5}'
  9. # 本地ip都是localhost,我们通常只关心端口
  10. ss -tunl | awk '/tcp/{print $5}' | awk -F: '{print $NF}'
  11. # 查看所有tcp的本地连接与远程连接
  12. ss | awk '/tcp/{print $5,$6}'
复制代码
统计tcp连接中状态数量

  1. # 查看TIME-WAIT数量
  2. ss -a | awk 'BEGIN {count=0;} $1=="tcp" && $2=="TIME-WAIT"{count++}END{print "TIME-WAIT数量:",count}'
  3. # 利用数组查看不同状态的数量
  4. ss -a|awk '/^tcp/{++s[$2]}END{for(a in s)print a,s[a]}'
复制代码
统计访问日志中404的数量

  1. # 先看一下是否匹配正确
  2. head server_access_log | awk '{print $9}'
  3. awk 'BEGIN {count=0;} $9==404{count++}END{print "404数量:",count}' server_access_log
复制代码
查看本机ip地址

  1. ifconfig | grep inet | awk '{print $2}'
复制代码
统计文件夹下文件巨细

  1. # 统计某个文件夹下的文件占用的字节数
  2. ll | awk 'BEGIN {size=0;} {size=size+$5;} END{print "文件夹下文件总大小:",size}'
  3. # M单位换算
  4. ll | awk 'BEGIN{size=0;} {size=size+$5;} END{print "文件夹下文件总大小:",size/1024/1024,"M"}'  
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

瑞星

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表