SHELL脚本学习(十四)gawk进阶

一、使用变量

gawk支持两种变量

  • 内建变量
  • 自定义变量
1.1 内建变量
1.1.1 字段和记录分隔符变量

数据字段变量允许使用美元符号 $ 和 位置来引用对应的字段。 $1 对应第一个数据字段,$2对应第二个数据字段,以此类推。

数据字段用字段分隔符划定。默认情况下,字段分隔符是一个空白字符(空格或制表符)。可以通过 -F选项修改字段分隔符。也可以使用特殊的内建变量FS修改字段分隔符。

有一组内建变量可以控制输入和输出数据中字段和记录的处理方式:

gawk数据字段和记录变量

变 量描 述
FIELDWIDTHS由空格分隔的一串数字,定义了每个数据字段的确切宽度
FS输入字段分隔符
RS输入记录分隔符
OFS输出字段分隔符
ORS输出记录分隔符
$ cat < data1
header line
data line 1
End of data line

#默认情况
$ gawk '{print $1,$2}' data1
header line
data line
End of

#1、OFS测试

$ gawk 'BEGIN{OFS="|-|"}
{print $1,$2}' data1
header|-|line
data|-|line
End|-|of

#2、ORS测试

$ gawk 'BEGIN{ORS="|-|"}
{print $1,$2}
END{print "\n"}' data1 
header line|-|data line|-|End of|-|

默认输出字段分隔符是空格,第1个例子将输出字段分隔符换成了"|-|“。
默认输出记录分隔符是换行,第2个例子将输出记录分隔符换成了”|-|"。

FIELDWIDTHS会根据提前设置好的字段宽度来划分字段。

下面这个例子将固定格式的时间划分成 年、月、日、时、分

$ cat <data2
202401011015
202402020900
202403030130

$ gawk 'BEGIN{
FIELDWIDTHS="4 2 2 2 2 2"}
{print $1,$2,$3,$4,$5}' data2
2024 01 01 10 15 
2024 02 02 09 00 
2024 03 03 01 30 

FS默认为空白符,RS默认为换行符。也就是说gawk默认一行为一条记录。但有时一行数据是一个字段,多行数据组成一条记录。这时可以将FS设置成\n,将RS设置成空字符串。

$ cat <data3
zhangsan
17
haerbin

lisi
20
beijing

$ gawk 'BEGIN{FS="\n";RS=""}
{print"name:"$1,"age:"$2,"city:"$3}' data3
name:zhangsan age:17 city:haerbin
name:lisi age:20 city:beijing

1.1.2 数据变量

除了字段和记录分隔符变量外,gawk还提供了其他一些变量帮助了解数据的变化。

更多的gawk内建变量

变量描述
ARGC命令行参数的数量
ARGIND当前处理的文件在ARGV中的索引
ARGV包含命令行参数的数组
CONVFMT数字的转换格式(参见printf语句),默认为%.6g
ENVIRON当前环境变量及其值组成的关联数组
ERRNO当读取或关闭输入文件发生错误时的系统错误号
FILENAME用作gawk输入的数据文件的名称
FNR当前数据文件中已处理的记录数
IGNORECASE非0表示忽略大小写
NF数据文件中的字段总数
NR已处理的输入记录数
OFMT数字的输出格式。默认值为%.6g。以浮点数或科学计数法表示,以较短者为准,最多是使用6位小数
RLENGTH由match函数所匹配的子串长度
RSTART由match函数所匹配的子串的起始位置

下面测试几个常用的变量

#ARGC:命令行参数的数量
#ARGV:当前处理的文件在ARGV中的索引
$ gawk 'BEGIN{print ARGC,ARGV[0],ARGV[1],ARGV[2]}' data1 data2
3 gawk data1 data2

#ENVIRON:当前环境变量及其值组成的关联数组
$ gawk 'BEGIN{print ENVIRON["HOME"]}' 
/home/ubuntu

#FILENAME :用作gawk输入的数据文件的名称
$ gawk 'END{print FILENAME}' data1
data1
$ cat < data1
header line
data line 1
End of data line

$ cat <data2
202401011015
202402020900
202403030130

#NR:已处理的输入记录数
#FNR:当前数据文件中已处理的记录数
#NF:数据文件中的字段总数
#$NF:最后一个字段的值
$ gawk '{print "NR="NR,"FNR="FNR,"NF="NF,"$NF="$NF}' data1 data2
NR=1 FNR=1 NF=2 $NF=line
NR=2 FNR=2 NF=3 $NF=1
NR=3 FNR=3 NF=4 $NF=line
NR=4 FNR=1 NF=1 $NF=202401011015
NR=5 FNR=2 NF=1 $NF=202402020900
NR=6 FNR=3 NF=1 $NF=202403030130
NR=7 FNR=4 NF=0 $NF=

1.2 自定义变量

gawk的自定义变量由任意个字母、数字和下划线组成,但不能以数字开头。
gawk自定义变量区分大小写。

1.2.1 在脚本中为变量赋值
$ gawk 'BEGIN{test="this is a test.";print test}'
this is a test.

$ gawk 'BEGIN{test=100;print test*(test-1)}'
9900

$ gawk 'BEGIN{test=100;print test^2}'
10000
1.2.2 在命令行中给变量赋值
$ cat <data1
header line
data line 1
End of data line

$ gawk '{print $field}'  field=1 data1
header
data
End

$ gawk '{print $field}'  field=2 data1
line
line
of

这个例子通过在命令行中给变量赋值,可以显示不同的字段。
这个特性可以在不改变脚本代码的情况下改变脚本的行为。

使用命令行参数定义变量有一个问题:设置变量后,这个变量在BEGIN模块不可用
如下:

$ gawk 'BEGIN {print "field="field}' field=3 data1
field=

可以用 -v选项解决这个问题。-v选项允许在BEGIN之前定义变量。

$ gawk -v field=3 'BEGIN {print "field="field}' field=3 data1
field=3
二、处理数组

数组用于单个变量存储多个值,gawk语言使用关联数组提供数组功能。类似c++中的unorder_map。

2.1 定义数组变量

可以用赋值语句定义数组变量。格式如下;

var[index]=element
var:数组变量名
index:索引
element:索引对应的值

$ gawk 'BEGIN{arr["name"]="lilei";arr["age"]=20;
print arr["name"],arr["age"]}'
lilei 20
2.2 遍历数组变量

格式:

for index in array
{
 statement
}

for语句每次循环时会把下一个数组元素的索引赋值给index。

$ gawk 'BEGIN{arr["name"]="lilei";arr["age"]=20;
for (ind in arr)
{
print "arr["ind"]="arr[ind]
}}'
arr[age]=20
arr[name]=lilei

索引没有固定的返回顺序。

2.3 删除数组变量

从关联数组中删除数据需要使用 delete 命令;

delete array[index]

下面使用delete命令的例子

$ cat < gawk_cmd
BEGIN {
    arr["name"]="lilei";
    arr["age"]=20;
    arr["city"]="haerbin";
    for (ind in arr)
    {
        print "arr["ind"] :" arr[ind];
    }
    delete arr["age"];
    print "---------"
    for (ind in arr)
    {
        print "arr["ind"] :" arr[ind];
    }
}

$ gawk -f gawk_cmd
arr[age] :20
arr[city] :haerbin
arr[name] :lilei
---------
arr[city] :haerbin
arr[name] :lilei

每行代码后面的分号 ( ; ) 写不写都行。

三、 使用模式
3.1 正则表达式

sed 只支持基础正则表达式(BRE),gawk支持基础正则表达式(BRE) 和扩展正则表达式(ERE)。

下面的第1个例子输出张三的年龄,第2个例子输出年龄在20~30之间的人的名字。

$ cat <data3
zhangsan
17
haerbin

lisi
20
beijing

$ gawk 'BEGIN{FS="\n";RS=""}
/zhangsan/{print $2}' data3
17

$ gawk 'BEGIN{FS="\n";RS=""}
/2./{print $1}' data3
lisi
3.2 匹配操作符

匹配操作符 (~) 使用格式:

数据字段 ~ /正则表达式/

和上面的例子相同,下面第1个例子输出zhangsan的年龄,第2个例子输出年龄在20~30之间的人的名字。


$ gawk 'BEGIN{FS="\n";RS=""}
$1 ~ /zhangsan/{print $1,$2,$3}' data3
zhangsan 17 haerbin

$ gawk 'BEGIN{FS="\n";RS=""}
$2 ~ /^2.$/{print $1,$2,$3}' data3
lisi 20 beijing

3.3 数学表达式

处理正则表达式,gawk还可以在匹配模式中使用数学表达式。
可以使用任何常见的数学表达式:

操作符描述
==等于
<=小于等于
<小于
>大于
>=大于等于

还是相同的例子,输出张三的年龄

$ cat <data3
zhangsan
17
haerbin

lisi
20
beijing

$ gawk 'BEGIN{FS="\n";RS=""}
$1=="zhangsan"{print "age="$2}' data3
age=17

四、结构化命令

gawk 中的结构化命令和 c语言 中的分支和循环结构基本一致。

4.1 if语句

输出年龄是否大于18岁

$ cat <data3
zhangsan
17
haerbin

lisi
20
beijing


$ cat < gawk_cmd
BEGIN {
   FS="\n"
   RS=""
   print "Begin"
}

{
    cmp=""
    age=18
    if ($2 <= age)
    {
        cmp=" less than "
    }
    else
    {
        cmp=" greater than "
    }
    print $1 cmp,age
}

END{
    print "End of file"
}


$ gawk -f gawk_cmd data3
Begin
zhangsan less than  18
lisi greater than  18
End of file

4.2 while 语句

格式:

while (condition)
{
 statements
}

下面例子输出某次跳远比赛各个选手的平均成绩。

$ cat < data1
5.5 6.5 7.5
6.6 6.5 6.5
6.6 7.5 5.9

$ cat < gawk_cmd
BEGIN {
   print "Begin"
}

{
    i=1
    sum=0.0
    while (i <= NF)
    {
        sum+=$i
        i++
    }
    print sum/NF
}

END{
    print "End of file"
}

$ gawk -f gawk_cmd data1
Begin
6.5
6.53333
6.66667
End of file
4.3 do-while语句

格式:

do
{
 statements
}
while (condition)

do-whilewhile 唯一区别是 do-while保证statements会在条件被求值之前至少执行一次。

4.4 for语句

格式:

for (变量赋值; condition; 迭代处理)
{
 statements
}

下面使用for语句计算跳远比赛的平均成绩。

$ cat < gawk_cmd
BEGIN {
   print "Begin"
}

{
    sum=0.0
    for(i=1;i<=NF;i++)
    {
        sum+=$i
    }
   
    print sum/NF
}

END{
    print "End of file"
}

$ gawk -f gawk_cmd data1
Begin
6.5
6.53333
6.66667
End of file
五、格式化打印
5.1 printf 命令

gawk中的printf命令和 C语言 中的printf函数一样。
格式:

printf “format string”,var1,var2…

格式说明符的控制字母

控制字母描述
c数字作为ASCII字符显示
d和i显示整数值
e用科学计数法显示数字
f显示浮点数
g用科学计数法或浮点数显示(较短的格式有限)
o显示八进制
s显示字符串
x显示十六进制
X显示十六进制,但用大写字母A-F
#将输入数据当做字符串
$ echo "200.33333"| gawk '{printf "%s\n",$1}'
200.33333

#将输入数据当作小数并保留两位小数
$ echo "200.33333"| gawk '{printf "%2.2f\n",$1}'
200.33

#将输入数据当作整数,并且至少输出5位,不足5位向前补0
$ echo "200.33333"| gawk '{printf "%05d\n",$1}'
00200
六、自定义函数
6.1 定义函数

格式:

function name ([variables])
{
  statements
}

6.2 使用函数

使用自定义函数计算平均成绩

$ cat < gawk_cmd
function average(s1,s2,s3)
{
    return (s1 + s2 + s3)/3
}

BEGIN {
   print "Begin"
   
}

{
    printf "average scores:%.2f\n",average($1,$2,$3)
}

END{
    print "End of file"
}


$ gawk -f gawk_cmd data1
Begin
average scores:6.50
average scores:6.53
average scores:6.67
End of file
6.3 函数库

也可以把常用的函数放到一个文件中,封装成函数库。

$ cat < lib_func
function average(s1,s2,s3)
{
    return (s1 + s2 + s3)/3
}

$ cat < lib_func
function average(s1,s2,s3)
{
    return (s1 + s2 + s3)/3
}
ubuntu@VM-8-14-ubuntu:~$ cat < gawk_cmd

BEGIN {
   print "Begin"
}

{
    printf "average scores:%.2f\n",average($1,$2,$3)
}

END{
    print "End of file"
}

$ gawk -f lib_func -f gawk_cmd  data1
Begin
average scores:6.50
average scores:6.53
average scores:6.67
End of file

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/762500.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

猫头虎 Gemma和Gemini模型的区别是什么?

猫头虎 &#x1f42f; Gemma和Gemini模型的区别是什么&#xff1f; 摘要&#x1f4d8; 在这篇文章中&#xff0c;我们将深入探讨Gemma和Gemini这两个由Google开发的AI模型。我们会对比它们的参数规模、计算资源需求和集成难度&#xff0c;帮助大家了解这两者之间的主要区别。…

【数据结构之B树的讲解】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

万字长文|下一代系统内存数据加速接口SDXI解读

本文内容分为5章节&#xff0c;总计10535字&#xff0c;内容较多&#xff0c;建议先收藏&#xff01; 1.SDXI技术产生的背景 2.SDXI相比DMA的优势 3.SDXI实现原理与架构 3.1 描述符环原理解读 3.2 上下文管理介绍 3.3 AKey与RKey解读 3.4 错误日志和状态管理 3.5 跨Function访…

【PLC】三菱PLC如何和汇川伺服实现485通信

前言 一开始选用的是汇川SV660P脉冲型伺服&#xff0c;由于生产需求需要对伺服的个别参数进行读取和写入操作&#xff0c;但是SV660P并不支持这种情况&#xff0c;因此需要使用485通信来满足。PLC这边选用的是三菱FX5U。 开始 1、首先准备按照下图的引脚提示准备好一根带屏蔽…

昇思25天学习打卡营第6天|简单的深度学习模型实战 - 函数式自动微分

自动微分(Automatic Differentiation)是什么&#xff1f;微分是函数在某一处的导数值&#xff0c;自动微分就是使用计算机程序自动求解函数在某一处的导数值。自动微分可用于计算神经网络反向传播的梯度大小&#xff0c;是机器学习训练中不可或缺的一步。 这些公式难免让人头大…

【C++】红黑树及其实现

目录 一、红黑树的定义1.为什么提出红黑树&#xff1f;2.红黑树的概念3.红黑树的性质 二、红黑树的实现1.红黑树的结构2.红黑树的插入2.1 uncle为红色2.2 uncle为黑色&#xff0c;且是grandfather的右孩子2.3 uncle为黑色&#xff0c;且是grandfather的左孩子 3.红黑树的验证 4…

SQLAlchemy(alembic)和Flask-SQLAlchemy入门教程

SQLAlchemy 是 Python 生态中最流行的 ORM 类库&#xff0c;alembic 用来做 OMR 模型与数据库的迁移与映射&#xff0c;Flask-SQLAlchemy 是 Flask 的扩展&#xff0c;可为应用程序添加对 SQLAlchemy 的支持&#xff0c;简化 SQLAlchemy 与 Flask 的使用。 一.SQLAlchemy 和 a…

C++——vector类用法指南

一、vector的介绍 1、vector是表示可变大小数组的序列容器 2、就像数组一样&#xff0c;vector也采用连续存储空间来存储元素。也就意味着可以采用下标对vector的元素进行访问&#xff0c;和数组一样高效。但又不像数组&#xff0c;它的大小是可以动态改变的&#xff0c;而且它…

Linux C 程序 【01】最小程序

1.开发背景 基于 RK3568 平台的基础上&#xff0c;编译一个在系统上运行的最小程序。 2.开发需求 由于 RK3568 作为宿主机&#xff0c;在上面编译程序比较慢&#xff0c;所以还是采用在 Ubuntu 下交叉编译后再拷贝到宿主机上运行。 设计实验&#xff1a; 1&#xff09;搭建 M…

嵌入式学习——硬件(IIC、ADC)——day56

1. IIC 1.1 定义&#xff08;同步串行半双工通信总线&#xff09; IIC&#xff08;Inter-Integrated Circuit&#xff09;又称I2C&#xff0c;是是IICBus简称&#xff0c;所以中文应该叫集成电路总线。是飞利浦公司在1980年代为了让主板、嵌入式系统或手机用以连接低速周边设备…

mybatis实现多表查询

mybatis高级查询【掌握】 1、准备工作 【1】包结构 创建java项目&#xff0c;导入jar包和log4j日志配置文件以及连接数据库的配置文件&#xff1b; 【2】导入SQL脚本 运行资料中的sql脚本&#xff1a;mybatis.sql 【3】创建实体来包&#xff0c;导入资料中的pojo 【4】User…

使用Colly库进行高效的网络爬虫开发

引言 随着互联网技术的飞速发展&#xff0c;网络数据已成为信息获取的重要来源。网络爬虫作为自动获取网页内容的工具&#xff0c;在数据分析、市场研究、信息聚合等领域发挥着重要作用。本文将介绍如何使用Go语言中的Colly库来开发高效的网络爬虫。 什么是Colly库&#xff1…

志愿者管理系统带讲解,保运行

技术栈 后端: SpringBoot Mysql MybatisPlus 前端: Vue Element 分为 管理员端 用户端 功能描述 用户端 管理员端 观看地址&#xff1a; B站 &#xff1a; 【毕设者】志愿者管理系统(安装讲解源码)

MQTT QoS 0, 1, 2

目录 # 开篇 1. 精细MQS TT QoS的行为 1.1 QoS 0: 最多交付一次&#xff08;At Most Once&#xff09; 1.2 QoS 1: 至少交付一次&#xff08;At Least Once&#xff09; 1.3 QoS 2: 只交付一次&#xff08;Exactly Once&#xff09; 1.4 传输过程图示 1.5 总结 2. MQTT…

如何避免爬取网站时IP被封?

互联网协议 (IP) 地址是识别网络抓取工具的最常见方式。IP 是每个互联网交换的核心&#xff0c;对其进行跟踪和分析可以了解很多有关连接客户端的信息。 在网络抓取中&#xff0c;IP 跟踪和分析&#xff08;又名指纹&#xff09;通常用于限制和阻止网络抓取程序或其他不需要的访…

面向阿克曼移动机器人(自行车模型)的LQR(最优二次型调节器)路径跟踪方法

线性二次调节器&#xff08;Linear Quadratic Regulator&#xff0c;LQR&#xff09;是针对线性系统的最优控制方法。LQR 方法标准的求解体系是在考虑到损耗尽可能小的情况下, 以尽量小的代价平衡其他状态分量。一般情况下&#xff0c;线性系统在LQR 控制方法中用状态空间方程描…

汇聚荣拼多多电商好不好?

拼多多电商好不好?这是一个值得探讨的问题。拼多多作为中国领先的电商平台之一&#xff0c;以其独特的商业模式和创新的营销策略吸引了大量用户。然而&#xff0c;对于这个问题的回答并不是简单的好或不好&#xff0c;而是需要从多个方面进行综合分析。 一、商品质量 来看拼多…

【源码+文档+调试讲解】居家养老系统

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了居家养老系统的开发全过程。通过分析高校学生综合素质评价管理方面的不足&#xff0c;创建了一个计算机管理居家养老系统的方案。文章介绍了居家养老系统的系统分…

jvm性能监控常用工具

在java的/bin目录下有许多java自带的工具。 我们常用的有 基础工具 jar:创建和管理jar文件 java&#xff1a;java运行工具&#xff0c;用于运行class文件或jar文件 javac&#xff1a;java的编译器 javadoc&#xff1a;java的API文档生成工具 性能监控和故障处理 jps jstat…

Sourcecodester Fantastic Blog CMS v1.0 SQL 注入漏洞(CVE-2022-28512)

前言 CVE-2022-28512 是一个存在于 Sourcecodester Fantastic Blog CMS v1.0 中的 SQL 注入漏洞。攻击者可以通过 "/fantasticblog/single.php" 中的 id 参数注入恶意 SQL 查询&#xff0c;从而获得对数据库的未经授权的访问和控制。 漏洞详细信息 漏洞描述: 该漏…