Linux三剑客之AWK

工作原理

# awk -F: '{print $1,$3}' /etc/passwd

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

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

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

语 法

==command(时空)

BEGIN{} {} END{} :

  • BEGIN{} begin发生在行处理前(注意大写);
  • {} 行处理时,读一行执行一次;
  • END{} 行处理后。

例:

# awk 'BEGIN{print 1/2}{print "-----";print $0}END{print "HOHO"}' /etc/hosts
0.5
-----
127.0.0.1 localhost localhost.localdomain localhost4
localhost4.localdomain4
-----
::1 localhost localhost.localdomain localhost6
localhost6.localdomain6
HOHO

内部变量:

  • F****S 输入字段分隔符(默认空格) # awk 'BEGIN{FS=":"} {print $1,$3}' /etc/passwd | head -1;
  • OFS 输出字段分隔符 # awk -F: 'BEGIN{FS=":";OFS="+++"}{print $1,$2,$3,$4}' /etc/passwd root+++x+++0+++0;
  • RS :输入记录(行)分隔符,默认换行符。请注意,在此时记录已经不是行的概念了。分隔符由”换行符“换成了”空格“;
  • ORS :输出记录(行)分隔符,默认换行符;
  • FNR :多文件独立编号;
  • NR :多文件汇总编号;
  • NF :字段总数 # awk -F: '{print NF, $0}' /etc/passwd。

格式化输出

1. print 函数

[root@localhost ~]# awk -F: '{print "username is: " $1
"\t uid is: " $3}' /etc/passwd | head -1
username is: root uid is: 0

2. printf 函数

  • %s 字符类型;
  • %d 数值类型;
  • %f 浮点型,可以定义保留;
  • 占15字符;
  • - 表示左对齐,默认是右对齐;
  • printf默认不会在行尾自动换行,加\n;
  • , 逗号,输出字段分隔符。

模式和动作

1. 概念

任何awk语句都由模式和动作组成。

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

2. 字符串比较

# awk '/^root/' /etc/passwd
# awk '$0 ~ /^root/' /etc/passwd
# awk '$0!~/^root/' /etc/passwd
# awk -F: '$1 ~ /^root/' /etc/passwd

3. 数值比较

3.1 目的

比较表达式采用对文本进行比较,只有当条件为真,才执行指定的动作。比较表达式使用关系运算符,用于比较数字与字符串。

3.2 关系运算符

1)语法

运算符 含义 示例:

  • < 小于 x<y
  • <= 小于或等于 x<=y
  • == 等于 x==y
  • != 不等于 x!=y
  • >= 大于等于 x>=y
  • > 大于 x>y

2)示例

# 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

3.3 算术 运算

1)语法

+ - * / %(模) (幂23)

2)示例

# awk -F: '$3 * 10 > 500' /etc/passwd

4. 多条件

1)逻辑操作符和复合模式

语法:

  • && 逻辑与 a&&b
  • || 逻辑或 a||b
  • ! 逻辑非 !a

例:

# awk -F: '$1~/root/ && $3<=15' /etc/passwd
# awk -F: '$1~/root/ || $3<=15' /etc/passwd
# awk -F: '!($1~/root/ || $3<=15)' /etc/passwd

2)范围模式

语法:

awk '/从哪里/,/到哪里/' filename。

例:

# awk -F: '/adm/,/lpd/' /etc/passwd

从adm到ldp,显示出来,注意避免匹配重复的字段。

AWK脚本编程

1. 变量

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

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

2. 条件&判断

1)if语句

格式:{if(表达式){语句;语句;...}}

2)if...else语句

格式:

  • {if(表达式){语句;语句;...}else{语句;语句;...}}
  • {if(){}else

3)if...else if...else语句

格式:

  • if (条件){动作}elseif(条件){动作}else
  • if(){}else if (){}else if(){}else{}

例:

  • 题目:统计出三种用户的数量;
  • 管理员数量:管理员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

3. 循环

1)while

  • 循环打印10个数字 awk 'BEGIN{ while(i<=10){print i; i++} }'
  • 每行打印十次 awk -F: '{ while(i<=9) {print $0; i++}}' passwd

2)for

  • 循环打印5个数字:awk 'BEGIN{for(i=1;i<=5;i++){print i} }'
  • 将每行打印10次:awk -F: '{ for(i=1;i<=10;i++) {print $0} }' /etc/passwd
  • 打印每一行的每一列:awk -F: '{ for(i=1;i<=NF;i++) {print $i} }' passwd

4. 数组

1)定义数组

将用户名定义为数组的值,打印第一个值。

# awk -F: '{username[++i]=$1} END{print username[1]}' /etc/passwd

2)数组遍历

  • 按索引遍历:
# awk -F: '{username[x++]=$1} END{for(i in username) {print i,username[i]} }' /etc/passwd
  • 按元素遍历(了解):
awk -F: '{username[x++]=$1} END{for(i=0;i<x;i++) print i,username[i]}' /etc/passwd

5. awk编程案例

1)统计/etc/passwd中各种类型shell的数量

awk -F: '{shells[$NF]++} END{ for(i in shells){print i,shells[i]} }' /etc/passwd

2)统计Apache/Nginx日志中的访问前十 <统计日志>

cat access_log |awk '{ips[$1]++} END{for(i in ips){print i,ips[i]} }' |sort -k2 -rn |head
posted @ 2023-08-07 10:25  寻梦99  阅读(16)  评论(0)    收藏  举报