【Linux】gawk编辑器二

devtools/2025/1/21 13:09:05/

一、变量

gawk编程语言支持两种变量:内建变量和自定义变量。

1、内建变量

gawk使用内建变量来引用一些特殊的功能。

字段和记录分隔符变量

数据字段变量

此变量允许使用美元符号($)和字段在记录中的位置值来引用对应的字段。要引用记录中的第一个数据字段,就用变量 $1,要引用第二个数据字段,就用变量 $2,以此类推。

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

gawk数据字段和记录变量
FIELDWIDTHS由空格分隔的一列数字,定义了每个数据字段的确切宽度
FS输入字段分隔符
RS输入记录分隔符
OFS输出字段分隔符
ORS输出记录分隔符

 默认情况下,gawk会将OFS变量的值设置为一个空格。print命令会自动将OFS变量的值置于输出的每个字段之间。

gawk 'BEGIN{FS=","} {print $1,$2,$3}' test2.txt

可以通过设置0FS变量,可以在输出中用任意字符串来分隔字段。

gawk 'BEGIN{FS=","; OFS="*"} {print $1,$2,$3}' test2.txt

 FIELDWIDTHS变量可以不通过字段分隔符读取记录。一旦设置了此变量,gawk就会忽略FS变量,并根据提供的字段宽度计算字段。

gawk 'BEGIN{FIELDWIDTHS="2 4 5 3"} {print $1,$2,$3,$4}' test3.txt

变量RSORS定义了gawk对数据流中记录的处理方式。默认情况下,gawk会将RS和ORS设置为换行符。

默认的RS值表明,输入数据流中的每行文本就是一条记录。

 包含地址和电话号码的数据中,占据了多行

可以把FS变量设置成换行符,这样就表明数据流中的每一行都是一个单独的字段,行内的所有数据都属于同一个数据字段。同时把RS变量设置成空字符串,然后在数据记录之间留一个空行。gawk就会把每一个空行视为记录分隔符。

 gawk 'BEGIN{FS="\n"; RS=""} {print $1,$3}' test3.txt

gawk将文件中的每一行都视为一个字段,同时将空行作为记录分隔符。 

 数据变量

ENVIRON变量使用关联数组来提取shell环境变量,其中关联数组用文本而非数值作为数组索引。

如下所示,可以用这种方法从shell中提取任何环境变量的值,以供gawk脚本使用。

gawk '
BEGIN{
print ENVIRON["HOME"]
print ENVIRON["PATH"]
}'

 变量FNR、NF和NR用于在gawk脚本中跟踪数据字段和记录。

变量NF可以让用户在不知道具体位置的情况下引用记录中的最后一个数据字段。NF变量含有数据文件中的最后一个字段的编号,在其前面加上美元符号,就把它用作字段变量。

gawk 'BEGIN{FS=":" ; OFS=":"} {print $1,$NF}' /etc/passwdgawk 'BEGIN{FS=":" ; OFS=":"} {$NF}' /etc/passwd

注意看执行两条命令后打印出来的区别之处。 

 FNR变量包含当前数据文件中已处理过的记录数,NR变量包含已处理过的记录总数。

gawk 'BEGIN{FS=","}{print $1, "FNR="FNR}' test2.txt test2.txt

上述gawk脚本在命令行中指定了两个输入文件(都是test2.txt),此脚本会打印第一个字段和FNR变量的当前值。 

gawk 'BEGIN{FS=","}{print $1, "FNR="FNR, "NR="NR}
END{print "这儿总共有",NR,"条记录被处理了"}'' test2.txt test2.txt

 在gawk处理第二个数据文件时,FNR变量的值被重置了,而NR变量则继续计数。

 因此,如果只使用一个数据文件作为输入,那么FNR和NR的值是相同的;如果使用多个数据文件作为输入,那么FNR的值会在处理每个数据文件时被重置,NR的值则会继续计数直到处理完所有的数据文件。

 2、自定义变量

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

在脚本中给变量赋值

在gawk脚本中给变量赋值与给shell脚本中的变量赋值一样,都使用赋值语句。

gawk '
BEGIN{
test1="测试……"
print test1
}'

 也可以保存数值或文本值:

gawk '
BEGIN{
test1="测试……"
print test1
test1=89
print test1
}'

还可以处理数学算式:

gawk 'BEGIN{x=7; x=x *9 + 10; print x}'

 在命令行中给变量赋值

可以在不修改脚本代码的情况下改变脚本的行为。

BEGIN{FS=","}
{print $n}
gawk -f test.sh n=3 test2.txt

 通过上述命令,可以显示文件中的第3个字段(n=3)。

使用命令行参数来定义变量值会产生一个问题:在设置过变量之后,这个值在脚本的BEGIN部分不可用

BEGIN{print "开始值是",n; FS=","}
{print $n}
gawk -f test.sh n=3 test2.txt

使用 -v 选项解决该问题,它允许在BEGIN部分之前设定变量。它必须放在脚本代码之前。

gawk -v n=3 -f test.sh test2.txt

 二、数组

gawk使用关联数组来提供数组的功能。与数字型数组不同,关联数组的索引可以是任意文本字符串,它用各种字符串来引用数组元素,每个索引字符串都必须能够唯一地标识出分配给它的数组元素。就跟其它语言中的哈希表、字典类似。

1、定义数组变量

使用标准赋值语句定义数组变量。

格式:var[index] = element

var:变量名;index:关联数组的索引值;element:数组元素值

gawk 'BEGIN{
capital["中国"] = "北京"
print capital["中国"]
}'

 2、遍历数组变量

在gawk脚本中遍历关联数组,使用for语句的一种特殊形式。

for {var in array}

{

 statements

}

此for语句会在每次循环时将关联数组array的下一个索引值赋给变量var,然后执行一遍statements。变量var中存储的是索引而不是数组元素值。

gawk 'BEGIN{
var["a"] = 10
var["h"] = 190
var["k"] = 78
var["t"] = "hello"
for (test in var)
{print "索引:",test," - 值:", var[test]
}
}'

如下所示,索引值没有固定的返回顺序。 

3、删除数组变量

 从关联数组中删除数组元素要使用一个特殊的命令:

delete array[index]

delete命令会从关联数组中删除索引值及其相关的数组元素值。

gawk 'BEGIN{
var["a"] = 10
var["h"] = 190
var["k"] = 78
var["t"] = "hello"
for (test in var)
{print "索引:",test," - 值:", var[test]
}delete var["k"]
print "*****"
for (test in var)
{ print "索引:",test," - 值:", var[test]
}
}'

三、使用模式

 gawk支持几种类型的匹配模式来过滤数据记录。比如,关键字BEGINEND可以在读取数据流之前或之后执行命令的特殊模式。

1、正则表达式

可以使用基础正则表达式(BRE)或扩展正则表达式(ERE)来筛选数据。

在使用正则表达式时,它必须出现在与其对应脚本的左花括号前。

# 匹配含有字符串“11”的数据
gawk 'BEGIN{FS=","} /11/{print $1}' test2.txt

#匹配用作字段分隔符的逗号
gawk 'BEGIN{FS=","} /,d/ {print $1}' test2.txt

2、匹配操作符

 匹配操作符(~)是一个很强大的工具,可以将正则表达式限制在记录的特定数据字段。可以指定匹配操作符、数据字段变量以及要匹配的正则表达式。

$1 ~ /^data/:此表达式会过滤出第一个数据字段以data开头的所有记录。

gawk 'BEGIN{FS=","} $2 ~ /^data3/{print $0}' test2.txt

匹配第2个数据字段要以“data3”开头的数据。 

可以用它在文件中搜索特定的数据元素。

gawk -F: '$1 ~ /csb/{print $1, $NF}' /etc/passwd

上面的脚本命令会在第一个数据字段中查找文本“csb”,如果匹配成功,则打印出第一个数据字段和最后一个数据字段。 

 也可以使用 ! 符号来排除正则表达式的匹配:

$1 !~ /expression/

gawk -F: '$1 !~ /^csb/{print $1,$NF}' /etc/passwd

匹配第一个数据字段不是以“csb”开头的数据, 如果匹配成功,则打印出第一个数据字段和最后一个数据字段。

3、数学表达式

显示出所有属于root用户组(组ID为0)的用户。

下面的gawk脚本会检查记录中值为0的第四个字段。 

gawk -F: '$4 == 0{print $1}' /etc/passwd

 也可以对文本数据使用表达式,但跟正则表达式不同,表达式必须完全匹配。

gawk -F, '$1 == "data"{print $1}' test2.txtgawk -F, '$1 == "data21"{print $1}' test2.txt

四、结构化命令

 1、if 语句

gawk编程语言支持标准格式的 if-then-else 语句。

gawk '{
if ($1 > 30)
{x = $1 * 2print x
}
}' test3.txt

gawk '{
if ($1 < 30)
{x = $1 * 2print x
} else
{x = $1 / 2print x
}}' test3.txt

 

 也可以在单行中使用else语句。

gawk '{if ($1 < 30) print $1 * 2; else print $1 / 2}' test3.txt

2、while语句

gawk '{
total = 0
i = 1
while (i <=3)
{total += $ii++
}
avg = total / 3
print "平均值是:", avg
}' test1.txt

还可以使用break语句和continue语句

gawk '{
total = 0
i = 1
while (i <= 3)
{total += $iif (i == 2)breaki++
}
avg = total / 2
print "前两个数据的平均值是:", avg
}' test1.txt 

 

3、do-while语句

do-while语句与while语句类似,但会在检查条件语句之前先执行命令。

gawk '{
total = 0
i = 1
do
{total += $ii++
} while (total < 200)
print total
}' test1.txt 

4、for语句

gawk '{
total = 0
for (i = 1; i <=3; i++)
{total += $i
} 
avg = total /3
print "平均值是:",avg
}' test1.txt 

五、格式化打印

和C语言编程一样,gawk中的格式化打印命令 printf 可以控制如何显示数据

格式:printf "format string, var1, var2

format string是格式化输出的关键,它会用文本元素和格式说明符来具体指定如何呈现格式化输出。格式说明符是一种特殊的代码,可以指明显示什么类型的变量以及如何显示。

1、控制字母

gawk脚本会将每个格式说明符作为占位符,供命令中的每个变量使用。第一个格式说明符对应列出第一个变量,第二个对应第二个变量,以此类推。

格式说明符的控制字母
c将数字作为ASCII字符显示
d显示整数值
i显示整数值
e用科学计数法显示数字
f显示浮点值
g用科学计数法或浮点数显示(较短的格式优先)
o显示八进制值
s显示字符串
x显示十六进制值
X用大写字母显示十六进制值
gawk 'BEGIN{
x = 10 * 10000
printf "结果是:%e\n", x
}'

 2、修饰符

除了控制字母,还有3种修饰符可以进一步控制输出。

width

指定输出字段的最小宽度。如果输出短于这个值,则printf会将文本右对齐,并用空格进行填充。如果输出比指定的宽度长,则按实际长度输出。

prec

指定浮点数中小数点右侧的位数或者字符串中显示的最大字符数。

减号 - 

指明格式化空间中的数据采用左对齐而非右对齐

在同一行中打印多个输出。

gawk 'BEGIN{FS=","} {printf "%s ", $1} END{printf "\n"}' test2.txt

 使用修饰符格式化第一个字符串的值

gawk 'BEGIN{FS="\n"; RS=""} {printf "%10s %s\n", $1, $2}' test1.txt

使用printf处理浮点值 

gawk '{
total = 0
for (i = 1; i <=3; i++)
{total += $i
}
avg = total / 3
printf "平均值是:%8.1f\n",avg
}' test3.txt

%8.1f强制printf命令将浮点值近似到小数点后一位。 

六、内置函数 

gawk编程语言提供了一些内置函数用于执行一些常见的数学、字符串以及时间运算。

1、数学函数

gawk数学函数
atan(x,y)x/y的反正切,x和y以弧度为单位
cos(x)x的余弦,x以弧度为单位
exp(x)x的指数
int(x)x的整数部分,取靠近0一侧的值
log(x)

x的自然对数

rand()比0大且比1小的随机浮点数
sin(x)x的正弦,x以弧度为单位
sqrt(x)

x的平方根

srand(x)为计算随机数指定一个种子值
and(v1,v2)对v1和v2执行按位AND运算
comp1(v1)对v1执行补运算
lshift(val,count)将val左移count位
or(v1,v2)对v1和v2执行按位OR运算
rshift(val,count)将val右移count位
xor(v1,v2)对v1和v2执行按位XOR运算

 产生较大随机整数的常见方法是综合运用rand()函数和int()函数:

x = int(10 * rand())

上述命令会返回一个0~9(包括0和9)的随机整数值。

2、字符串函数

gawk字符串函数
index(s,t)返回字符串t在字符串s中的索引位置;如果没找到,则返回0
length([s])返回字符串s的长度;如果没有指定,则返回$0的长度
match(s,r [,a])返回正则表达式r在字符串s中匹配位置的索引。如果指定了数组a,则将s的匹配部分保存在该数组中
split(s,a [,r])将s以FS(字段分隔符)或正则表达式r(如果有指定的话)分割并放入数组a中。返回分割后的字段总数
sub(r,s [,t])在变量$0或目标字符串t中查找匹配正则表达式r的部分。如果找到了,就用字符串s替换第一处匹配
substr(s,i [,n])返回s中从索引 i 开始、长度为n的子串。如果未提供n,则返回s中剩下的部分
tolower(s)将s中的所有字符都转换成小写
toupper(s)将s中的所有字符都转换成大写
gawk 'BEGIN{x = "ning"; print toupper(x); print length(x)}'

3、时间函数

时间函数多用于处理日志文件。日志文件中一般含有需要进行比较的日期。通过将日期的文本表示形式转换成纪元时(自1970-01-01 00:00:00 UTC到现在的秒数),可以做到很容易就比较日期。

gawk时间函数
mktime(dataspec)将一个按YYYY MM DD HH MM SS [DST]格式指定的日期转换成时间戳
strftime(format [, timestamp])将当前时间的时间戳或timestamp(如果提供了的话)转化成格式化日期(采用shell命令date的格式)
systime()返回当前时间的时间戳
gawk 'BEGIN{
date = systime()
day = strftime("%A, %B %d, %Y", date)
print day
}'

 

七、自定义函数

 可以在gawk脚本中自己创建函数。

1、定义函数

定义自己的函数,必须使用function关键字。

function name([variables])

{  

  statements

}

function myrand(limit)
{  return int(limit * rand())
}

2、使用自定义函数

定义函数时,它必须出现在所有代码块之前(包括BEGIN代码块)。

gawk '
function myrand(limit)
{  return int(limit * rand())
}
BEGIN{x = myrand(8)print x
}'

3、创建函数库

gawk提供了一种方法可以将多个函数放入单个库文件中。

首先,创建一个包含所有gawk函数的文件

# 函数库名:functionlib
function myrand(limit)
{  return int(limit * rand())
}function myprint()
{printf "%-16s - %s\n", $1, $4
}function printthird()
{print $3
}

接着,使用函数库时,只要创建好gawk脚本文件,然后在命令行中同时指定库文件和脚本文件即可。

# gawk脚本名 test
BEGIN{ FS="\n"; RS=""}
{myprint()
}

然后执行下述命令即可。(-f选项不能和内联gawk脚本一起使用,所以要在同一命令行中使用多个 -f 选项。) 

gawk -f functionlib -f test test2.txt


http://www.ppmy.cn/devtools/152355.html

相关文章

string底层实现细节

一、部分代码展示 #pragma once #include<cstring> #include<cassert> #include<iostream> using namespace std; namespace bit {class string{public:// 迭代器类指针// 范围for就是在编译时替换成迭代器遍历&#xff0c;*it返回给chtypedef char* iterat…

B站评论系统的多级存储架构

以下文章来源于哔哩哔哩技术 &#xff0c;作者业务 哔哩哔哩技术. 提供B站相关技术的介绍和讲解 1. 背景 评论是 B站生态的重要组成部分&#xff0c;涵盖了 UP 主与用户的互动、平台内容的推荐与优化、社区文化建设以及用户情感满足。B站的评论区不仅是用户互动的核心场所&…

Unity2021.3.13崩溃的一种情况

如果出现如下的报错&#xff0c;可能是软件冲突的原因。自己的原因是使用f.lux这款软件似乎和Unity相互冲突&#xff0c;出现下面报错。 错误信息如上图

单例及线程池的实现及感悟分享

碎碎念&#xff1a; 有快3个月没有写博客了&#xff0c;这段时间很多事&#xff0c;抽不出空来写博客。后面的博客可能风格也会转变&#xff0c;从理论到实战为主&#xff0c;尽量减少源码的解读。(看完源码后面自己也忘了QAQ&#xff09;&#xff0c;本篇博客主要介绍线程池的…

TinyEngine v2.1版本发布:全新的区块方案和画布通信方案,打造更强力的可拓展低代码引擎

前言 2025年蛇年已经到来&#xff0c;TinyEngine v2.1.0 版本也已经蛇气腾腾的发布了出来&#xff0c;新年新气象&#xff0c;为了让大家更详细了解到 v2.1.0 的内容更新&#xff0c;我们特此列举了该版本中的一些重要特性更新。 v2.1.0变更特性概览 1、使用了新的纯前端区块…

MIAOYUN信创云原生项目亮相西部“中试”生态对接活动

近日&#xff0c;以“构建‘中试’生态&#xff0c;赋能科技成果转化”为主题的“科创天府智汇蓉城”西部“中试”生态对接活动在成都高新区菁蓉汇隆重开幕。活动分为成果展览、“中试”生态主场以及成果路演洽谈对接三大板块。在成果展览环节&#xff0c;成都元来云志科技有限…

OpenHarmony API 设计规范

OpenHarmony API 设计规范 修订记录 版本作者时间更新内容v0.1&#xff0c;试运行版OpenHarmony API SIG2022年11月初版发布 目的 API是软件实现者提供给使用者在编程界面上的定义&#xff0c;API在很大程度上体现了软件实体的能力范围。 同时&#xff0c;API定义的好坏极…

《鸿蒙 HarmonyOS 应用开发从入门到精通(第 2 版)》学习笔记 ——HarmonyOS 环境搭建之安装DevEco Studio

作为一款开发工具&#xff0c;除了具有基本的代码开发、编译构建及调测等功能外&#xff0c;DevEco Studio还具有如下特点&#xff1a; 高效智能代码编辑&#xff1a;支持Java、XML、ArkTS、JS、C/C等语言的代码高亮、代码智能补齐、代码错误检查、代码自动跳转、代码格式化、…