gawk

gawk

虽然sed编辑器是非常方便自动修改文本文件的工具,但其也有自身的限制。通常你需要一个用来处理文件中的数据的更高级工具,它能提供一个类编程环境来修改和重新组织文件中的数据。这正是gawk能够做到的。

gawk程序是Unix中的原始awk程序的GNU版本。gawk程序让流编辑迈上了一个新的台阶,它提供了一种编程语言而不只是编辑器命令。在gawk编程语言中,你可以做下面的事情:
 定义变量来保存数据;
 使用算术和字符串操作符来处理数据;
 使用结构化编程概念(比如if-then语句和循环)来为数据处理增加处理逻辑;
 通过提取数据文件中的数据元素,将其重新排列或格式化,生成格式化报告。
gawk命令格式
gawk程序的基本格式如下:
gawk程序脚本用一对花括号来定义。
由于gawk命令行假定脚本是单个文本字符串,你还必须将脚本放到单引号中。
gawk options program file
gawk '{print "Hello World!"}'
-F fs 指定行中划分数据字段的字段分隔符
-f file 从指定的文件中读取程序
-v var=value 定义gawk程序中的一个变量及其默认值
-mf N 指定要处理的数据文件中的最大字段数
-mr N 指定数据文件中的最大数据行数
-W keyword 指定gawk的兼容模式或警告等级
使用数据字段变量
使用数据字段变量
gawk的主要特性之一是其处理文本文件中数据的能力。它会自动给一行中的每个数据元素分配一个变量。默认情况下,gawk会将如下变量分配给它在文本行中发现的数据字段:
 $0代表整个文本行;
 $1代表文本行中的第1个数据字段;
 $2代表文本行中的第2个数据字段;
 $n代表文本行中的第n个数据字段。
gawk -F: '{print $1}' /etc/passwd
#指定分割符为: 然后过滤第一列字符

 在程序脚本中使用多个命令:

[root@localhost advanced_shell_script]# echo "my name is tom" |gawk '{$4="robin";print $0}' 
 my name is robin
#多个命令用; 分隔,$0 代表整个字符串。定义的字符 robin 要用""

 从文件中读取程序

[root@localhost gawk]# cat test1.gawk 
{print $1 "'s home directory is" $6}
[root@localhost gawk]# gawk -F: -f test1.gawk /etc/passwd
root's home directory is/root
bin's home directory is/bin
daemon's home directory is/sbin
adm's home directory is/var/adm

 多行命令

[root@localhost gawk]# cat test1.gawk 
{print $1 "'s home directory is" $6}
{print $1}
[root@localhost gawk]# gawk -F: -f test1.gawk /etc/passwd
root's home directory is/root
root
bin's home directory is/bin
bin

或者

[root@localhost gawk]# cat test1.gawk 
text="'s home directory is"
{print $1  text $6}
[root@localhost gawk]# gawk -F: -f test1.gawk /etc/passwd
root:x:0:0:root:/root:/bin/bash
root's home directory is/root

 在处理数据前运行脚本

[root@localhost gawk]# gawk 'BEGIN {print "The data file contents"}{print $0}' /etc/fstab 
The data file contents

#
# /etc/fstab
# Created by anaconda on Tue Feb 26 18:42:10 2019
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'

 在处理数据后运行脚本

[root@localhost gawk]# gawk 'BEGIN {print "hehe"} 
> {print $0}
> END {print "haha"}' data1
hehe
test text
haha
[root@localhost gawk]# 

 使用模式

正则表达式

 gawk 'BEGIN{FS=","} /11/{print $1}' data1

匹配操作符

匹配操作符(matching operator)允许将正则表达式限定在记录中的特定数据字段。匹配操作符是波浪线(~)。可以指定匹配操作符、数据字段变量以及要匹配的正则表达式。
[root@localhost gawk]# gawk 'BEGIN{FS=" "}$1 ~ /^123/{print $1}' data1
123
[root@localhost gawk]# gawk -F: '$1 ~ /^zhengyue/{print $1,$NF}' /etc/passwd
zhengyue /bin/bash
[root@localhost gawk]# 

数学表达式

可以使用任何常见的数学比较表达式。
 x == y:值x等于y。
 x <= y:值x小于等于y。
 x < y:值x小于y。
 x >= y:值x大于等于y。
 x > y:值x大于y。
也可以对文本数据使用表达式,但必须小心。跟正则表达式不同,表达式必须完全匹配。数据必须跟模式严格匹配。

查看passwd 文件中属组是root 的用户

[root@localhost gawk]# gawk -F: '$4 == 0{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
operator:x:11:0:operator:/root:/sbin/nologin
[root@localhost gawk]# 

gawk 结构化命令

  if 语句

if (condition) 
 statement1
[root@localhost gawk]# cat data3
10
20
30
[root@localhost gawk]# gawk '{
if ($1>10)
{
x = $1 * 2
print x
}
}' data3
40
60
[root@localhost gawk]# 
[root@localhost gawk]# cat data3
10
20
30
[root@localhost gawk]# gawk '{
if ($1>10)
{
x = $1 * 2
print x
} else
{
x = $1 / 2
print x
}}' data3
5
40
60
[root@localhost gawk]# 

while 循环语法

[root@localhost gawk]# cat data4
130 120 135 
160 113 140 
145 170 215
[root@localhost gawk]# gawk '{
total = 0
i = 1
while (i < 4)
{
total += $i
i++
}
avg = total / 3
print "Average:", avg
}' data4
Average: 128.333
Average: 137.667
Average: 176.667
[root@localhost gawk]# 
while语句会遍历记录中的数据字段,将每个值都加到total变量上,并将计数器变量i增值。
当计数器值等于4时,while的条件变成了FALSE,循环结束,然后执行脚本中的下一条语句。
这条语句会计算并打印出平均值。这个过程会在数据文件中的每条记录上不断重复。

do-while 语句

do-while语句类似于while语句,但会在检查条件语句之前执行命令。下面是do-while语句的格式。
do 
{ 
 statements 
} while (condition)
[root@localhost gawk]# cat data4
130 120 135 
160 113 140 
145 170 215
[root@localhost gawk]# gawk '{         #正常是while ,,,do,,,done 这个流程, do while  理解就是先执行一遍循环体的内容,然后进行判断。符合就继续执行do ,不符合就执行后续的命令, 
total = 0                  #这里的 print total 是在循环体外执行的, 把 do while 看成 while do 然后先执行 do 就好理解了
i = 1
do
{
total += $i
i++
} while (total < 150)
print total }' data4
250
160
315
[root@localhost gawk]# 

for 语句

for语句是许多编程语言执行循环的常见方法。gawk编程语言支持C风格的for循环。
for( variable assignment; condition; iteration process) 
将多个功能合并到一个语句有助于简化循环。
[root@localhost gawk]# cat data4
130 120 135 
160 113 140 
145 170 215
[root@localhost gawk]#  gawk '{ 
 total = 0 
 for (i = 1; i < 4; i++) 
 { 
 total += $i 
 } 
 avg = total / 3 
 print "Average:",avg 
 }' data4
Average: 128.333
Average: 137.667
Average: 176.667
[root@localhost gawk]# 

内建函数

数学函数

gawk             数学函数
函 数            描 述
atan2(x, y)       x/y的反正切,x和y以弧度为单位
cos(x)            x的余弦,x以弧度为单位
exp(x)            x的指数函数
int(x)            x的整数部分,取靠近零一侧的值
log(x)            x的自然对数
rand( )           比0大比1小的随机浮点值
sin(x)            x的正弦,x以弧度为单位
sqrt(x)           x的平方根
srand(x)          为计算随机数指定一个种子值

 

字符串函数

gawk                  字符串函数
函 数               描 述
asort(s [,d])      将数组s按数据元素值排序。索引值会被替换成表示新的排序顺序的连续数字。另外如果指定了d,则排序后的数组会存储在数组d中
asorti(s [,d])     将数组s按索引值排序。生成的数组会将索引值作为数据元素值,用连续数字索引来明排序顺序。另外如果指定了d,排序后的数组会存储在数组d中
gensub(r, s, h [, t]) 查找变量$0或目标字符串t(如果提供了的话)来匹配正则表达式r。如果h是一个以g或G开头的字符串,就用s替换掉匹配的文本。如果h是一个数字,它表示要替换掉第处r匹配的地方
gsub(r, s [,t])    查找变量$0或目标字符串t(如果提供了的话)来匹配正则表达式r。如果找到了,就全部替换成字符串s
index(s, t)       返回字符串t在字符串s中的索引值,如果没找到的话返回0
length([s])       返回字符串s的长度;如果没有指定的话,返回$0的长度
match(s, r [,a])  返回字符串s中正则表达式r出现位置的索引。如果指定了数组a,它会存储s中匹配则表达式的那部分22.6 内建函数 489 

split(s, a [,r])  将s用FS字符或正则表达式r(如果指定了的话)分开放到数组a中。返回字段的总数sprintf(format, variables) 用提供的format和variables返回一个类似于printf输出的字符串
sub(r, s [,t])    在变量$0或目标字符串t中查找正则表达式r的匹配。如果找到了,就用字符串s替换掉第一处匹配
substr(s, i [,n])  返回s中从索引值i开始的n个字符组成的子字符串。如果未提供n,则返回s剩下的部分
tolower(s)        将s中的所有字符转换成小写
toupper(s)        将s中的所有字符转换成大写
[root@localhost gawk]# gawk 'BEGIN{x = "testing"; print toupper(x);print length(x)}'   #常用方式
TESTING
7

时间函数

gawk 的时间函数
函 数                              描 述
mktime(datespec)              将一个按YYYY MM DD HH MM SS [DST]格式指定的日期转换成时间戳值①
strftime(format [,timestamp]) 将当前时间的时间戳或timestamp(如果提供了的话)转化格式化日期(采用shell函数date()的格式)
systime( )                   返回当前时间的时间戳
[root@localhost gawk]# gawk 'BEGIN{
date = systime()
print date
day = strftime("%A , %B ,%d , %Y",date)
print day
}'
1555921121
星期一 , 四月 ,22 , 2019
[root@localhost gawk]# 
原文地址:https://www.cnblogs.com/zy09/p/10722030.html