【Shell 编程三剑客】shell-awk命令详解(理论+实战)

目录

一、概述

 1.2、工作原理

1.3、工作流程

1.4、 运行模式

1.5、 执行流程

1.6、 基本语法

二、实战案列

2.1、内建变量

2.2、内置变量

2.3、BEGIN 和 END 运算


一、概述

20世纪70年代诞生于贝尔实验室,现在centos7用的是gawk。

AWK 是一种处理文本文件的语言,是一个强大的文本分析工具。
之所以叫 AWK 是因为其取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字符
linux中有三剑客之称:
三剑客功能:
[awk]:  处理文本
grep : 过滤文本
sed  :  修改文本
awk:全称Aho, Weinberger, Kernighan,报告生成器,格式化文本输出,GNU/Linux发布的AWK目前由自 由软件基金会(FSF)进行开发和维护,通常也称它为 GNU AWK。 它是专门为文本处理设计的编程语言,也是行处理软件,通常用于扫描、过滤、统计汇总工作 数据可以来自标准输入也可以是管道或文件。
有多种版本:
  • AWK:  原先来源于 AT & T 实验室的的AWK
  • NAWKNew awkAT & T 实验室的AWK的升级版  
  • GAWK:即GNU AWK。所有的GNU/Linux发布版都自带GAWK,它与AWKNAWK完全兼容
linux 上常用的是 gawk,awk gawk 的链接文件

 1.2、工作原理

1. 初始化阶段

  • 在处理文件之前,awk会执行BEGIN语句块(如果存在)。BEGIN语句块主要用于初始化变量、设置输出格式等准备工作,它与文件内容无关,只执行一次。

2. 逐行处理阶段

  • awk逐行读取输入文件(或标准输入)的内容。对于每一行,它会执行以下操作:
    • 分割字段:根据指定的字段分隔符(默认为空格或制表符),将当前行分割成多个字段。每个字段都可以通过内置的变量(如$1$2等)来访问。
    • 模式匹配:检查当前行是否匹配用户定义的模式(如果有的话)。模式可以是正则表达式、条件表达式等。
    • 执行操作:如果当前行匹配了模式,则执行与该模式相关联的操作。操作可以包括打印文本、计算表达式、赋值变量等。
    • 重复处理:这个过程会重复进行,直到文件中的所有行都被处理完毕。

3. 汇总阶段

  • 在处理完所有行之后,awk会执行END语句块(如果存在)。END语句块主要用于输出汇总信息、执行清理工作等,也只执行一次。

当读到第一行时,匹配条件,然后执行指定动作,再接着读取第二行数据处理,不会默认输出
如果没有定义匹配条件默认是匹配所有数据行, awk 隐含循环,条件匹配多少次动作就会执行多少次逐行读取文本,默认以空格或tab 键为分隔符进行分隔,将分隔所得的各个字段保存到内建变量中,并按 模式或者条件执行编辑命令。
sed 命令常用于一整行的处理,而 awk 比较、倾向于将一行分成多个 "" 字段 " 然后再进行处理。 awk
信息的读入也是逐行读取的,执行结果可以通过 print 的功能将字段数据打印显示。
在使用 awk 命令的过程中, 可以使用逻辑操作符 " &&" 表示 " " "|| 表示 " " "!" 表示非 ";
还可以进行简单的数学运算,如 + 、 *、 / % ^ 分别表示加、减、乘、除、取余和乘方。

任何 awk 语句都是由模式动作组成,一个 awk 脚本可以有多个语句。

模式决定动作语句的触发条件和触发时间

模式是一个条件表达式,用于决定哪些输入行应该被处理。模式可以是以下几种类型之一:

  • 正则表达式:如果当前行与给定的正则表达式匹配,则执行相应的动作。
  • 关系表达式:如果当前行的字段满足某个条件(如大于、小于等),则执行相应的动作。
  • BEGIN和END模式BEGIN模式在读取任何输入行之前执行一次,而END模式在所有输入行都被读取和处理之后执行一次。
  • 空模式:如果没有指定模式,则对所有输入行执行动作

动作是当模式匹配时执行的语句块。它通常包含awk命令,用于对输入行或字段进行处理,如打印、赋值、计算等。动作可以是一个或多个awk语句,这些语句被大括号{}包围

1.3、 运行模式

  • 正则表达式 : /root/ 匹配含有 root 的行 /*.root/
  • 关系表达式: < > && || + *
  • 匹配表达式: ~ ~ 动作:
  • 变量 、命令、 内置函数 、流控制语句   它的语法结构如下:

1.4、 执行流程

BEGIN 语句设置计数和打印头部信息,在任何动作之前进行
END 语句输出统计结果,在完成动作之后执行
AWK 执行的流程非常简单:读( Read )、执行( Execute )与重复( Repeat )。
下面的流程图描述出 了AWK 的工作流程

BEGIN后面的花括号内容优先处理,BEGIN后的动作完成后再处理后面的

1.5、 基本语法

命令格式
如果动作较为复杂,也可以将动作写在一个单独的文件中,并使用 -f选项来指定该文件:
awk -f 脚本文件 文件 1 文件 2 ..
格式: awk  选项    命令部分 '{xxxx}' 文件名

二、实战案列

2.1、内建变量(重要)

内建变量(也称为内置变量或预定义变量,可直接使用

awk 包含几个特殊的内建变量(可直接用)如下所示:
FS 指定 每行文本的字段 分隔符 ,默认为空格或制表位。
NF :当前处理的 行的字段个数
NR :当前处理的 行的行号 (序数)。
$0 :当前处理的行的 整行内容
$n :当前处理行的第 n 个字段(第 n 列)。
FILENAME :被处理的文件名。
RS: 行分隔符。 awk 从文件上读取资料时 , 将根据 Rs 的定义把资料切割成许多条记录 , awk 一次仅读入一 条记录, 以进行处理。预设值是 " \n'
简说:数据记录分隔,默认为 \n ,即每行为一条记录
变量名描述
FS指定每行文本的字段分隔符,默认为空格或制表位。
NF当前处理的行的字段个数(即列的个数)。
NR当前处理的行的行号(序数)。
$0当前处理的行的整行内容。
$n当前处理行的第n个字段(第n列),其中n是一个数字。例如:$1表示第一个字段,$2表示第二个字段。
FILENAME被处理的文件名(当前输入文件的名)。
FNR各文件分别计数的行号,对于每个新文件,FNR会从1开始重新计数。
OFS输出字段分隔符(默认值是一个空格)。
ORS输出记录分隔符(默认值是一个换行符)。
RS行分隔符。awk从文件上读取资料时,将根据RS的定义把资料切割成许多条记录,awk一次仅读入一条记录进行处理。预设值是\n,即每行为一条记录。
①、FS的作用
FS指定分隔符为:  并且$1  第一列
在打印之前先定义字段分隔符为冒号

②、NF的作用

即列的个数

 打印每一行的列数,列的个数

③、NR的作用

行号

④、 $0的作用

一整行内容

它包含一个模式(/root/)和一个动作({print $0})。

  • /root/:这是一个正则表达式模式,用于匹配包含“root”的行。当 awk 扫描到匹配这个模式的行时,就会执行后面的动作。
 awk -F: '/root/{print $0}' /etc/passwd
搜索包含root的整行内容,全部打印出来

⑤、$n(1>n为数字)的作用
 awk 默认把这一行当做一列,因为没有被空格分隔, awk 默 认以空格或tab 键分隔
awk  '{print $1}'  /etc/passwd

⑥、FILENAME(filename)的作用

就是提示处理文件的名字

⑦、FNR的使用

记录行号顺序

⑧、OFS的使用

分隔符为空格,输出分隔符为@@

默认情况下,OFS的值是空格。

⑨、RS的用法

行分隔符,注意是行

分行的时候按照---来分割

变成=这样了

 record1
 record2
 record3  iiii   a1
 b2
 c3

$1是列

F或者FS是只有看列的时候,才会按照---来分隔(分列的的时候按照---来分割)

⑩、ORS

在每行后添加行分隔符

NF的作用

NR的作用

显示行号

 awk -F:  '{print "第" NR "行有" NF "列" }' /etc/passwd

 

在打印一遍

awk '{print "hello" }' </etc/passwd

直接打印内容

自定义冒号为分隔符显示分隔之后的第五列
awk -F: '{print $5}' /etc/passwd

// 定义多个分隔符,只要看到其中一个都 算作分隔符
awk -F[:/] '{print $1}' /etc/passwd

awk 常用内置变量: $1 $2 NF NR $0
$1 :代表第一列
$2 :代表第二列以此类推
$0 :代表整行
NF :一行的列数
NR :行数

 
打印包含root的行的第 一列
打印包含root的行的 第一列和第六列
默认应该整行
 

多一个$0就多显示行内容

nr行数,可以不用print 直接默认显示

当然也可以加上效果一样

awk 'NR==2{print}' /etc/passwd //同上效果

打印第二行的第一列
awk -F:  'NR==2{print $1}' /etc/passwd

打印最后每行一列

awk -F: '{print $NF}' /etc/passwd

打印总行数
awk END'{print NR}' /etc/passwd

打印文件最后一行


 

 扩展生产案列:网卡的ip、流量

查看流量

查看ip地址

查看磁盘空间

2.3、BEGIN 和 END 运算

逐行执行开始之前执行什么任务,结束之后再执行什么任务,用 BEGIN END ,BEGIN一般用来做初始化操作,仅在读取数据记录之前执行一次
END 一般用来做汇总操作,仅在读取完数据记录之后执行一次。

小数也可以运算,不指定初始值,初始值就为0,如果是字符串,则默认为空。^**都是幂运算,

BEGIN 在处理文件之前,所以后面不跟 文件名也不影响。

模糊匹配,用 ~ 表示包含, !~ 表示不包含
awk -F: '$1~/ro/' /etc/passwd // 模糊匹配,只要有 ro 就匹配上

awk -F:  '$7!~/nologin$/{print $1,$7}' /etc/passwd

关于数值与字符串的比较
比较符号: == != <= >= < >
第五行
和5行内
加“”代表精确查找

3到100列的

逻辑运算 && ||
&& || 是逻辑运算符,用于组合多个条件并控制程序流程。
&& 要求所有条件都为真时才为真,否则为假。
|| 只要有一个条件为真就为真,全为假时才为假。
打印 1-200 之间所有能被 7 整除并且包含数字 7 的整数数字

其他内置变量的用法 FS (输入)、 OFS NR FNR RS ORS
FS :输入字段的分隔符 默认是空格
OFS :输出字段的分隔符 默认也是空格
FNR :读取文件的记录数(行号),从 1 开始,新的文件重新重 1 开始计数
RS :输入行分隔符 默认为换行符
ORS :输出行分隔符 默认也是为换行符

 

OFS的作用
OFS 定义了输出时以什么分隔, $1 $2 中间要用逗号分隔,因为逗号默认被映射为 OFS 变量,而这个变量默认是空格
OFS :输出分隔符 默认也是空格,我们这里是---,然后输出$2
awk 'BEGIN{FS=":";OFS="---"}{print $1,$2}' /etc/passwd

FNR
awk '{print FNR,$0}' /etc/resolv.conf /etc/hosts
可以看出 FNR的行号在追加当有多个文件时

NR
awk '{print NR,$0}' /etc/resolv.conf /etc/hosts
  • NR代表当前记录号(即当前行号,在整个输入文件中是唯一的)。
  • $0代表当前记录的内容,即当前行的全部文本。

因此,'{print NR,$0}'这个动作的意思是“打印当前行号(NR)和当前行的全部内容($0)”。

FNR区分文件给行号,NR不区分

RS
指定以什么为换行符,这里指定是冒号,指定的肯定是原文里存在的字符
ORS
把多行合并成一行 输出,输出的时候自定义以空格分隔每行,本来默认的是回车键

2.4、awk高级用法

定义引用变量
将系统的变量 a(提前有值为10) ,在 awk 里赋值为变量 b ,然后调用变量 b     -v 选项将其传递给 awk
awk 'BEGIN{print "'$a'"}'
直接调用的话需要先用双引号再用单引号,双单

awk 直接定义变量并引用

awk -vc=1 'BEGIN{print c}'

调用函数 getline ,读取一行数据的时候并不是得到当前行而是当前行的下一行
df -h |awk 'BEGIN{getline}/root/{print $0}'
显示偶数行,也是调用getline函数
seq 10 | awk '{print $0;getline}' // 显示奇数行

2.5、awk if语句

awk if 语句也分为单分支、双分支和多分支
awk -F: '{if($3<10){print $0}}' /etc/passwd
第三列小于10的打印出来
awk -F: '{if($3<10){print $3}else{print $1}}' /etc/passwd
多了一个else输出

2.6、AWK 数组

P awk 数组的下标除了可以使用数字,也可以使用字符串,字符串需要使用双引号
awk 'BEGIN{a["abc"]=10;a[1]=20;print a["abc"]}'

2.7、awk 循环

awk 'BEGIN{a[0];a[1]=20;a[2]=20;for(i in a){print i,a[i]}}'

使用 awk 统计 httpd 访问日志中每个客户端 IP 的出现次数 ?
awk '{a[$1]+=1}END{for(i in a){print a[i]" "i}}' /var/log/httpd/access_log| sort -r
备注 : 定义数组,数组名称为 ip ,数字的下标为日志文件的第 1 列(也就是客户端的 IP 地址 ) ++ 的目的在于对客户端进行统计计数,客户端IP 出现一次计数器就加 1 END 中的指令在读取完文件后执行,通过循环将所有统 计信息输出,for 循环遍历的是数组名 ip 的下标。
可用 awk 来统计固定格式日志里的一些数据,如日志中出现过所有不同的 IP
awk 对文件进行流处理,每次读取一行。 $1 就是 IP count[i] ++ 是将 IP 作为一个数组的下标,并且使得统计这个IP 所对应的数组元素自增 1.END 后面的语句是打印结果,只执行一次。
awk '{i=$1;count[i]++}END{for(i in count)print(i,count[i])}' /var/log/httpd/access_log
试题
1.怎么提取版本号 1 .9.7 给你道面试题
ant-1.9.7.jar
ant-launcher-1.9.7.jar
antlr-2.7.7.jar
antlr-runtime-3.4.jar
aopalliance-1.0.jar
archaius-core-0.7.6.jar
asm-5.0.4.jar
aspectjweaver-1.9.5.jar
bcpkix-jdk15on-1.64.jar
bcprov-jdk15-1.46.jar
bcprov-jdk15on-1.64.jar
checker-compat-qual-2.5.5.jar
只用出来1.9.7
2. 需求 :1.txt 文件中的内容 帅选出第一列 第三列 并且打印为一行,同时需求两列内容相隔 2 个空格
zhangsan 20 江苏南京 汉族 内容 文件名称 1.txt

2.8、总结

  • grep egrep 文本过滤 (更适合单纯的查找或匹配文本)
  • sed 流编辑器 实现编辑的(更适合编辑匹配到的文本)
  • awk 文本报告生成器 实现格式化文本输出(更适合格式化文本,对文本进行较复杂格式处理)

BEGIN中的命令只执行一次 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值