Linux三剑客:awk的高级用法

目录

awk高级用法

awk控制语句---if-else判断

awk控制语句---while循环

awk控制语句---do-while循环

awk控制语句---for循环

shell脚本中较相似的控制语句

break和continue

next

awk数组

awk自定义函数

[awk中调用shell 命令](#awk中调用shell 命令)


这一篇主要介绍awk的高级用法,因为awk可以单独作为一门语言来使用,所以它有很多高级用法

awk高级用法

awk控制语句---if-else判断

(1)语法

if(condition){statement;...}[else statement]  双分支
if(condition1){statement1}else if(condition2){statement2}else{statement3}  多分支

(2)使用场景:对awk 取得的整行或某个字段做条件判断

(3)演示

演示文本awkdemo内容:

bash 复制代码
hello:world
linux:redhat:lalala:hahaha
along:love:youou

---打印出了如果/etc/passwd下的第三个字段即uid大于3小于1000的第1列和第3列

bash 复制代码
[root@centos111 test]# awk -F: '{if($3>10 &&$3<1000)print $1,$3}' /etc/passwd
operator 11
games 12
...

---打印出如果最后一列是"bin/bash"的则打印出第一列和最后一列

bash 复制代码
[root@centos111 test]# awk -F: '{if($NF=="/bin/bash")print $1,$NF}' /etc/passwd
root /bin/bash
amandabackup /bin/bash
user /bin/bash
user1 /bin/bash
user2 /bin/bash

---输出总列数大于3的行

bash 复制代码
[root@centos111 test]# awk -F: '{if(NF>3) print $0}' awkdemo 
linux:redhat:lalala:hahaha

---第3列>=1000为Common user,反之是root or Sysuser

bash 复制代码
[root@centos111 test]# awk -F: '{if($3>=1000){printf "Conmmon user:%s\n",$1} else{printf "root or Sysuser:%s\n",$1}}' /etc/passwd
root or Sysuser:root
...
Conmmon user:nfsnobody
...

---磁盘利用率超过40的设备名和利用率

bash 复制代码
[root@centos111 test]# df -h|awk -F% '/^\/dev/{print $1}'|awk '$NF > 40{print $1,$NF}'
/dev/mapper/centos-root 56

---test=100和>90为very good; 90>test>60为good; test<60为no pass

bash 复制代码
[root@centos111 test]# awk 'BEGIN{ test=100;if(test>90){print "very good"}else if(test>60){ print "good"}else{print "no pass"}}'
very good

[root@centos111 test]# awk 'BEGIN{ test=80;if(test>90){print "very good"}else if(test>60){ print "good"}else{print "no pass"}}'
good

[root@centos111 test]# awk 'BEGIN{ test=50;if(test>90){print "very good"}else if(test>60){ print "good"}else{print "no pass"}}'
no pass

awk控制语句---while循环

(1)语法

bash 复制代码
while``(condition){statement;...}

注:条件"真",进入循环;条件"假", 退出循环

(2)使用场景

对一行内的多个字段逐一类似处理时使用

对数组中的各元素逐一处理时使用

(3)演示

---以along开头的行,以:为分隔,显示每一行的每个单词和其长度

bash 复制代码
[root@centos111 test]#  awk -F: '/^along/{i=1;while(i<=NF){print $i,length($i); i++}}' awkdemo
along 5
love 4
youou 5

---以:为分隔,显示每一行的长度大于6的单词和其长度

bash 复制代码
[root@centos111 test]# awk -F: '{i=1;while(i<=NF) {if(length($i)>=6){print $i,length($i)}; i++}}' awkdemo
redhat 6
lalala 6
hahaha 6

---计算1+2+3+...+100=5050

bash 复制代码
[root@centos111 test]# awk 'BEGIN{i=1;sum=0;while(i<=100){sum+=i;i++};print sum}' 5050
5050

awk控制语句---do-while循环

1)语法

bash 复制代码
do` `{statement;...}``while``(condition)

意义:无论真假,至少执行一次循环体

(2)计算1+2+3+...+100=5050

bash 复制代码
[root@centos111 test]# awk 'BEGIN{sum=0;i=1;do{sum+=i;i++}while(i<=100);print sum}'
5050

awk控制语句---for循环

(1)语法

bash 复制代码
for``(expr1;expr2;expr3) {statement;...}

(2)特殊用法:遍历数组中的元素

bash 复制代码
for``(var ``in` `array) {``for``-body}

(3)演示

---显示每一行的每个单词和其长度

bash 复制代码
[root@centos111 test]# awk -F: '{for(i=1;i<NF;i++){print$i,length($i)}}' awkdemo 
hello 5
linux 5
redhat 6
lalala 6
along 5
love 4
//NF表示字段数量,

---求男m、女各自的平均

bash 复制代码
[root@along ~]# cat sort.txt
xiaoming m 90
xiaohong f 93
xiaohei m 80
xiaofang f 99
[root@centos111 test]# awk '{m[$2]++;score[$2]+=$3}END{for(i in m) {printf "%s:%6.2f\n",i,score[i]/m[i]}}' sort.txt 
m: 85.00
f: 96.00

shell脚本中较相似的控制语句

break和continue

bash 复制代码
---奇数相加
[root@centos111 test]# awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==0)continue;sum+=i}print sum}'
2500

---1+2+...+66
[root@centos111 test]# awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i==66)break;sum+=i}print sum}'
2145

---奇数相加``
[root@centos111 test]# awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==0)continue;sum+=i}print sum}'
2500

---1+2+...+66``
[root@centos111 test]# awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i==66)break;sum+=i}print sum}'
2145

next

next:提前结束对本行处理而直接进入下一行处理(awk 自身循环)

---只打印偶数行

bash 复制代码
[root@centos111 test]# awk -F: '{if(NR%2!=0) next; print $1,$3}' /etc/passwd
bin 1
adm 3
...

awk数组

关联数组:array[index-expression]

(1)可使用任意字符串;字符串要使用双引号括起来

(2)如果某数组元素事先不存在,在引用时,awk 会自动创建此元素,并将其值初始化为"空串"

(3)若要判断数组中是否存在某元素,要使用"index in array"格式进行遍历

(4)若要遍历数组中的每个元素 ,要使用for 循环**:for(var in array)** {for-body}

演示

bash 复制代码
[root@centos111 test]# cat awkdemo2
aaa
bbbb
aaa
123
123
123

---去除重复的行

bash 复制代码
[root@centos111 test]# awk '!arr[$0]++' awkdemo2
aaa
bbbb
123

---打印文件内容,和该行重复第几次出现

bash 复制代码
[root@centos111 test]# awk '{!arr[$0]++;print $0,arr[$0]}' awkdemo2
aaa 1
bbbb 1
aaa 2
123 1
123 2
123 3

分析:把每行作为下标,第一次进来,相当于print ias...一样结果为空,打印空,!取反结果为1,打印本行,并且++变为不空,下次进来相同的行就是相同的下标,本来上次的值,!取反为空,不打印,++变为不空,所以每次重复进来的行都不打印

(2)数组遍历

bash 复制代码
[root@centos111 test]# awk 'BEGIN{abc["ceo"]="along";abc["coo"]="mayun";abc["cto"]="mahuateng";for(i in abc){print i,abc[i]}}'coo mayun
ceo along
cto mahuateng
[root@centos111 test]#  awk '{for(i=1;i<=NF;i++)abc[$i]++}END{for(j in abc)print j,abc[j]}' awkdemo2
aaa 2
bbbb 1
123 3

数值\字符串处理

(1)数值处理

  • rand():返回0和1之间一个随机数,需有个种子 srand(),没有种子,一直输出0.237788

演示:

bash 复制代码
[root@centos111 test]# awk 'BEGIN{print rand()}' 
0.237788
[root@centos111 test]# awk 'BEGIN{srand();print rand()}' 
0.973507
[root@centos111 test]# awk 'BEGIN{srand();print rand()}' 
0.70811
---取0-50随机数
[root@centos111 test]# awk 'BEGIN{srand();print int(rand()*100%50)+1}' 
4
[root@centos111 test]# awk 'BEGIN{srand();print int(rand()*100%50)+1}' 
28

(2)字符串处理:

  • length([s]) :返回指定字符串的长度

  • sub(r,s,[t]) :对t 字符串进行搜索r 表示的模式匹配的内容,并将第一个匹配的内容替换为s

  • gsub(r,s,[t]) :对t 字符串进行搜索r 表示的模式匹配的内容,并全部替换为s 所表示的内容

  • plit(s,array,[r]) :以r 为分隔符,切割字符串s ,并将切割后的结果保存至array 所表示的数组中,第一个索引值为1, 第二个索引值为2,...

演示:

bash 复制代码
[root@centos111 test]# echo "2008:08:08 08:08:08" | awk 'sub(/:/,"-",$1)'
2008-08:08 08:08:08
//搜索第一个值然后替换
[root@centos111 test]# echo "2008:08:08 08:08:08" | awk 'gsub(/:/,"-",$1)'
2008-08-08 08:08:08
搜索所有的值进行替换
[root@centos111 test]# echo "2008:08:08 08:08:08" | awk '{split($0,i,":")}END{for(n in i){print n,i[n]}}'
4 08
5 08
1 2008
2 08
3 08 08

awk自定义函数

(1)格式:和bash区别:定义函数()中需加参数,return返回值不是$?,是相当于echo输出

bash 复制代码
function name ( parameter, parameter, ... ) {
    statements
    return expression
}

(2)演示

bash 复制代码
[root@centos111 test]# cat fun.awk 
function max(v1,v2) {
    v1>v2?var=v1:var=v2
    return var
}
BEGIN{a=3;b=2;print max(a,b)}
[root@centos111 test]# awk -f fun.awk 
3

awk中调用shell 命令

(1)system 命令

空格是awk 中的字符串连接符,如果system中需要使用awk中的变量可以使用空格分隔,或者说除了awk 的变量外其他一律用"" 引用 起来。

bash 复制代码
[root@centos111 test]# awk BEGIN'{system("hostname")}'
centos111

(2)向awk脚本传递参数

① 格式:

bash 复制代码
awkfile var=value var2=value2... Inputfile

注意 :在BEGIN 过程 中不可用。直到 首行输入完成以后,变量才可用 。可以通过**-v 参数**,让awk 在执行BEGIN 之前得到变量的值。命令行中每一个指定的变量都需要一个-v

② 示例

bash 复制代码
[root@centos111 test]# cat test.awk
#!/bin/awk -f
{if($3 >=min && $3<=max)print $1,$3}
[root@centos111 test]# chmod +x test.awk
[root@centos111 test]# ./test.awk -F: min=100 max=200 /etc/passwd
systemd-network 192
相关推荐
迷茫运维路3 分钟前
Jenkins声明式Pipeline流水线语法示例
运维·pipeline·jenkins·声明式
聪明的墨菲特i4 分钟前
Django前后端分离基本流程
后端·python·django·web3
工业3D_大熊11 分钟前
【虚拟仿真】CEETRON SDK在船舶流体与结构仿真中的应用解读
java·python·科技·信息可视化·c#·制造·虚拟现实
熊的猫14 分钟前
webpack 核心模块 — loader & plugins
前端·javascript·chrome·webpack·前端框架·node.js·ecmascript
SEEONTIME19 分钟前
python-24-一篇文章彻底掌握Python HTTP库Requests
开发语言·python·http·http库requests
Bearnaise20 分钟前
PointMamba: A Simple State Space Model for Point Cloud Analysis——点云论文阅读(10)
论文阅读·笔记·python·深度学习·机器学习·计算机视觉·3d
Zfox_20 分钟前
【Linux】进程信号全攻略(二)
linux·运维·c语言·c++
速盾cdn20 分钟前
速盾:vue的cdn是干嘛的?
服务器·前端·网络
安於宿命25 分钟前
【Linux】简易版shell
linux·运维·服务器
丶Darling.28 分钟前
MIT 6.S081 Lab1: Xv6 and Unix utilities翻译
服务器·unix·lab·mit 6.s081·英文翻译中文