shell编程 awk

awk


awk 是一种编程语言,用于在linux/unix下对文本和数据进行处理。
数据可以来自标准输入、一个或多个文件,或其它命令的输出。
它支持用户自定义函数和动态正则表达式等先进功能,

awk的处理文本和数据的方式是这样的,
它逐行扫描文件,从第一行到最后一行,
寻找匹配的特定模式的行,并在这些行上进行你想要的操作。
如果没有指定处理动作,则把匹配的行显示到标准输出(屏幕),

awk分别代表其作者姓氏的第一个字母。因为它的作者是三个人,
分别是Alfred Aho、Peter Weinberger、 Kernighan。

  • 工作原理
# awk -F: '{print $1,$3}' /etc/passwd

(1)awk使用一行作为输入,并将这一行赋给内部变量$0,每一行也可称为一个记录,以换行符结束

(2)然后,行被:(默认为空格或制表符)分解成字段(或域),每个字段存储在已编号的变量中,从$1开始,
最多达100个字段

(3)awk输出之后,将从文件中获取另一行,并将其存储在$0中,覆盖原来的内容,然后将新的字符串分隔
成字段并进行处理。该过程将持续到所有行处理完毕
在这里插入图片描述

语法:awk   [options]   'commands'      filenames (推荐)
  1. FS 输出字段分隔符(默认空格)
[root@localhost ~]# awk -F: '{print $1, $3}' /etc/passwd | head -1
root 0
或
[root@localhost ~]# awk -F'[ :\t]' '{print $1,$2,$3}' /etc/passwd | head -1
root x 0
或
[root@localhost ~]# awk 'BEGIN{FS=":"} {print $1,$3}' /etc/passwd | head -1
root 0
[root@localhost ~]# awk -F: '{print $1, $3}' /etc/passwd | head -1
root 0
或
[root@localhost ~]# awk -F'[ :\t]' '{print $1,$2,$3}' /etc/passwd | head -1
root x 0
或
[root@localhost ~]# awk 'BEGIN{FS=":"} {print $1,$3}' /etc/passwd | head -1
root 0
 [root@localhost ~]# awk -F: '{print $1,$2,$3,$4}' /etc/passwd | head -1
root x 0 0

[root@localhost ~]# awk -F: 'BEGIN{FS=":";OFS="+++"}{print $1,$2,$3,$4}' /etc/passwd | head -1
root+++x+++0+++0

  1. RS 输入记录(行)分隔符,默认换行符
[root@localhost ~]# awk   '{print $0}' a.txt 
111 222 333 444 555:666:777
[root@localhost ~]# awk 'BEGIN{RS="   "}{print $0}' a.txt 
111
222
333
444
555:666:777
在此时记录已经不是行的概念了。分隔符由”换行符“换成了”空格“


  1. ORS 输出记录(行)分隔符,默认换行符
[root@localhost ~]# awk 'BEGIN{RS=" ";ORS="+++"}{print $0}' a.txt 
111+++222+++333+++444+++555:666:777
输出记录分隔符换成了“+++”。

  1. FNR 多文件独立编号
    在这里插入图片描述
  2. NR 多文件汇总编号
    在这里插入图片描述
  3. NF 字段总数
[root@localhost ~]# awk -F: '{print NF,$0}' passwd
7 root:x:0:0:root:/root:/bin/bash1
7 bin:x:1:1:bin:/bin:/sbin/nologin2
7 daemon:x:2:2:daemon:/sbin:/sbin/nologin3
7 adm:x:3:4:adm:/var/adm:/sbin/nologin4
7 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin5
7 sync:x:5:0:sync:/sbin:/bin/sync6
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown7
7 halt:x:7:0:halt:/sbin:/sbin/halt8
7 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin9
7 operator:x:11:0:operator:/root:/sbin/nologin10


格式化输出 print 函数

[root@localhost ~]# date | awk '{print "year:"$2"\nmonth"$1}'
year:09月
month2020年

\n 换行符 文字输出 ,用引号

模式(正则表达)和动作
任何awk语句都由模式和动作组成。模式部分决定动作语句何时触发及触发事件。
如果省略模式部分,动作将时刻保持执行状态。每一行都会有动作。
模式可以是任何条件语句或复合语句或正则表达式。有模式的话,就是对模式对应的行进行动作。

  1. 字符串比较
# awk    '/^root/'     /etc/passwd
# awk '$0 ~ /^root/' /etc/passwd
# awk '$0!~/^root/' /etc/passwd
# awk -F: '$1 ~ /^root/' /etc/passwd

  1. 数值比较
    比较表达式采用对文本进行比较,只有当条件为真,才执行指定的动作。比较表达式使用关系运算符,
    用于比较数字与字符串。
    关系运算符
    运算符 含义 示例
    < 小于 x<y
    <= 小于或等于 x<=y
    == 等于 x==y
    != 不等于 x!=y

= 大于等于 x>=y
大于 x>y

示例
# awk -F: '$3 == 0' /etc/passwd 
# awk -F: '$3 == 1' /etc/passwd 
# awk -F: '$3 < 10' /etc/passwd
== 也可以用于字符串判断
# awk -F: '$7 == "/bin/bash"' /etc/passwd
# awk -F: '$1 == "alice"' /etc/passwd
算数 运算
+ - * / %() ^(幂2^3)
例:# awk -F: '$3 * 10 > 500' /etc/passwd


多条件
逻辑操作符和复合模式
语法
&&逻辑 两者都符合条件
| | 逻辑 两者之间复合一条条件
范围模式
语法
awk ‘/从哪里/,/到哪里/’ filename

  • awk脚本编程
  1. awk调用变量
    1)自定义内部变量
awk -v user=root -F: '$1 == user' /etc/passwd
-v定义变量

(2)外部变量

  • 双引号
# var="bash"
# echo "unix script" | awk "{print "123",\"$var\"}"
123 bash

注意 awk调用外部变量时,外部使用双引号,内部也使用双引号,但需要转义内部的双引号

  • 单引号
# var="bash"
# echo "unix script" |awk '{print $1,"'"$var"'"}'
unix  bash

注意使用单引号时,内部需要用双引转义

  • 条件&判断
    If 语句
格式:{if(表达式){语句;语句;...}
awk -F: '{if($3==0) {print $1 " is administrator."}}' /etc/passwd
如果$3是0,表名是管理员
Ifelse语句
格式:{if(表达式){语句;语句;...else{语句;语句;...}} {if(){}else{}}
awk -F: '{if($3==0){count++} else{i++}} END{print "管理员个数: "count ; print "系统用户数: "i}' /etc/passwd
统计管理员和系统用户数量

If …else if …else语句
(1)格式:{if(表达式1){语句;语句;…}else if(表达式2){语句;语句;…}else if(表达式3){语句;语句;…}else{语句;语句;…}}
(2)if (条件){动作}elseif(条件){动作}else{动作}
(3)if(){}else if (){}else if(){}else{}

[root@localhost ~]# awk -F:  '{if($3==0){print $1," is admin "}else if ($3>999){print $1," is user"}else {print $1, " is sofo user"}}'  /etc/passwd

显示出三种用户的信息
管理员:管理员ID为0 内置用户:用户ID<1000 普通用户: 用户ID>999

awk -F: '{if($3==0){i++} else if($3>999){k++} else{j++}} END{print "管理员个数: "i; print "普通用个数: "k; print "系统用户: "j}' /etc/passwd

统计出三种用户的数量
管理员数量:管理员ID为0 内置用户数量:用户ID<1000 普通用户数量: 用户ID>999

  • 循环
    While
循环打印10个数字:awk 'BEGIN{  while(i<=10){print i; i++} }'
第一行打印十次:awk -F: '{ while(i<=9) {print $0; i++}}'  passwd 
全部打印十次:awk –F:‘{i=1;while(i<=9){print $0;i++}}’  passwd
For
循环打印5个数字:awk ’BEGIN{for(i=1;i<=5;i++){print i}}’
全部打印十次:awk –F: ‘{for(i=1;i<=10;i++){print $0}}’  passwd
打印每一行每一列:awk –F: ‘{for(i=1;i<=NF;i++){print $i}}’ passwd

  • 数组
    定义数组
awk –F: ‘{username[i++]=$1}END{print username[1]}/passwd
root
数组遍历(按索引遍历)
awk –F: ‘{username[x++]=$1}END{for(I in username){print I,username[i]}}’  passwd | sort -n
统计一下/etc/passwd中各种类型shell得数量
Awk –F: ‘{shell[$NF]++}END{for(I in shells){print i, shells[i]}}/etc/passwd
/bin/sync 1
/bin/bash 9
/sbin/nologin 40
/sbin/halt 1
/sbin/shutdown 1
$NF 最后一列的字段内容
{}行处理
把统计的对象,作为索引。每次递增。
Print i  打印索引
Shells[i]  数组加索引,显示的就是值。
(1)打印datafile文件 number of fileds:字段数 最后输出
awk 'END {print "Number of fields: "NF}' datafile
(2)//三目运算符 a?b:c 条件?成立结果1:不成立结果2
第七列小于4显示high$7 第七列大于4显示low$7
awk '{print ($7 > 4 ? "high "$7 : "low "$7)}' datafile
(3)第三列正则匹配以Suan开头的,打印第6列加0.2 并且打印第八列
awk '$3 ~ /^Suan/ {print "Percentage: "$6 + .2 " Volume: " $8}' datafile
(4)找datafile文件中$3=Chris行赋值$3=Christian 打印所有列
awk '$3 == "Chris" {$3 = "Christian"; print $0}' datafile
(5)匹配Derek的行,为$8列赋值,$8=$8+12,再打印出$8
awk '/Derek/ {$8+=12; print $8}' datafile  
(6)//$7 %= 3等价于$7 = $7 % 3 先将第七列取余,再赋值给第七列,打印第七列
awk '{$7%=3; print $7}' datafile


在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值