转载:gawk 使用方法简介 - 简书 (jianshu.com)

gawk 是最初 Unix 系统上 awk 程序的 GNU 版本。相对于作为流式编辑器的 sed 而言,它提供了更为强大的编程语言特性。

其功能与特性包括:

  • 定义变量来存储数据
  • 通过代数运算符和字符串操作符来处理数据
  • 使用结构化编程语句如 if-then循环
  • 从数据文件中提取出有价值的字段再重新组合以生成结构化的报表

基本语法

gawk options program file

构成 gawk 脚本的语句须包含在一对大括号( {} )中,而作为命令选项的整个脚本需要包含在一对引号中:

$ cat test.txt
Hello World!
$ gawk '{print $0}' test.txt
Hello World!
1. 使用字段变量

gawk 会自动地将每行文本中的每个数据字段赋值给一个指定的变量,默认情况下,预先定义的变量为:

  • $0 表示一整行文本
  • $1 表示该行文本的第一个字段
  • $2 表示该行文本的第二个字段
  • $n 表示该行文本的第 n 个字段

文本行中的数据字段是通过预先定义的字段分隔符来分隔开的,默认为空格(包括 TAB

$ cat data.txt
One line of test text.
Two lines of test text.
Three lines of test text.
$ gawk '{print $1}' data.txt
One
Two
Three

可以通过 -F 选项指定另外的分隔符(如 ' , ' )

$ cat user.csv
Jack,male,20
Rose,female,18
Mike,male,24
$ gawk -F, '{print $1}' user.csv
Jack
Rose
Mike
2. 多个命令

gawk 语言允许在脚本语句中组合多个命令使用,只需要在各命令之间使用分号( ; )分隔开即可

$ echo "My name is Rich" | gawk '{$4="Christine"; print $0}'
My name is Christine

也可以这样:

$ gawk '{
> $4="Christine"
> print $0}'
My name is Rich
My name is Christine

其中 My name is Rich 是运行时程序获取的用户输入,My name is Christine 是程序运行后的输出

3. BEGIN & END

默认情况下,gawk 从输入中读取一行文本,再对该文本执行程序指令。而有时候需要在读取待处理数据之前先执行某些指令,此时就要用到BEGIN关键字。

同样的,END 关键字允许你指定在数据处理完成后才执行的脚本。

$ gawk 'BEGIN {print "The data File Contents:"}
> {print $0}
> END {print "End of File"}' data.txt
The data File Contents:
One line of test text.
Two lines of test text.
Three lines of test text.
End of File
4. 从文件中获取脚本

gawk 允许先将其程序脚本保存在某个文件中,再通过 -f 选项指定该文件的文件名。而在脚本文件中,各命令不再需要通过 ';' 符号分隔,直接分行列出即可。

$ cat script.gawk
BEGIN {
print "Users and their age"
print "User \t Age"
FS=","
}
{
print $1 " \t " $3
}
END {
print "There are three people"
}
$ gawk -f script.gawk user.csv
Users and their age
User Age
Jack 20
Rose 18
Mike 24
There are three people

上述脚本文件中的 FS="," 用于定义字段分隔符,效果等同于 -F 选项。

高级特性

1. 变量

程序语言最重要的特性之一就是定义和引用变量。gawk 语言支持两种类型的变量:内建变量和用户自定义变量。

gawk 程序在处理文本数据时,一次只读取一小段文本,称为 Record 。默认的 Record 分隔符即为换行符。而每条 Record 又可进一步划分成字段(Data Field),并按顺序依次赋值给 $1,$2,$n 等。默认的字段分隔符为空格(包括 TAB)

控制数据字段和 Record 的内建变量:
变量名 描述
FIELDWIDTHS 用一串由空格分隔的数字定义每个数据字段的具体宽度
FS 定义数据字段分割符(输入)
RS 定义 Record 分割符(输入)
OFS 定义数据字段分割符(输出)
ORS 定义 Record 分割符(输出)

默认的 OFS 为空格

$ gawk 'BEGIN{FS=","} {print $1,$2,$3}' user.csv
Jack male 20
Rose female 18
Mike male 24
$ gawk 'BEGIN{FS=",";OFS=":"} {print $1,$2,$3}' user.csv
Jack:male:20
Rose:female:18
Mike:male:24

当定义了 FIELDWIDTHS 变量时,gawk 在读取数据时就会忽略字段分割符(FS),转而使用字段宽度来分割数据。

$ cat numbers.txt
1005.3247596.37
11522.349194.00
05810.1298100.1
$ gawk 'BEGIN{FIELDWIDTHS="3 5 2 5"} {print $1,$2,$3,$4}' numbers.txt
100 5.324 75 96.37
115 22.34 91 94.00
058 10.12 98 100.1

有些时候会遇到如下组织方式的文本文件:

$ cat people.txt
Riley Mullen
123 Main Street
Chicago, IL 60601
(312)555-1234 Frank Williams
456 Oak Street
Indianapolis, IN 46201
(317)555-9876

此时可将字段分隔符(FS)设置为 "\n",Record 分隔符(RS)设置为空字符串,则 gawk 程序会将空行作为一条 Record 的终止点。

$ gawk 'BEGIN{FS="\n"; RS=""} {print $1,$4}' people.txt
Riley Mullen (312)555-1234
Frank Williams (317)555-9876
其他内建变量
变量 描述
ARGC 当前命令行参数的数目
ARGV 由命令行参数组成的数组
CONVFMT 数字的转换格式,默认值为 %.6 g
ENVIRON 包含当前系统环境变量的关联数组(字典)
ERRNO 当读取或关闭文件出现错误时返回的系统错误
FILENAME gawk 处理的数据文件的文件名
FNR 当前正在处理的 Record 序号
IGNORECASE 设置为非零值时忽略大小写
NF 数据文件中的字段序号
NR 已处理的 Record 总数
OFMT 数字的输出格式,默认为 %.6 g
$ gawk 'BEGIN{FS=",";
> print ARGC,ARGV[0],ARGV[1];
> print ENVIRON["HOME"]}
> {print FILENAME,FNR ":" $1}' user.csv
2 gawk user.csv
/Users/starky
user.csv 1:Jack
user.csv 2:Rose
user.csv 3:Mike

ARGV 的索引是从 0 开始的,表示第一个命令行参数(呃,所以通常就是 gawk 这个命令本身)。程序脚本(引号中的内容)不算在参数内。

用户自定义变量
  • 在脚本中定义变量
$ gawk '
> BEGIN{
> testing = "This is a test"
> print testing
> testing = 45
> print testing
> }'
This is a test
45
$ gawk 'BEGIN{x = 4; x = x * 2 + 3; print x}'
11
  • 在命令行参数中定义变量
$ cat script1.gawk
BEGIN{FS = ","}
{print $n}
$ gawk -f script1.gawk n=1 user.csv
Jack
Rose
Mike
2. 数组

定义数组:var[index]=element

$ gawk 'BEGIN{
> var[1] = 34
> var[2] = 3
> total = var[1] + var[2]
> print total
> }'
37

遍历数组:

for (var in array)
{
statements
}
$ gawk 'BEGIN{
> var["a"] = 1
> var["g"] = 2
> var["m"] = 3
> var["u"] = 4
> for (test in var)
> {
> print "Index:",test," Value:",var[test]
> }
> }'
Index: u Value: 4
Index: m Value: 3
Index: a Value: 1
Index: g Value: 2

关联数组遍历的顺序是随机的

3. 模式匹配
正则表达式
$ cat user.csv
Jack,male,20
Rose,female,18
Mike,male,24
$ gawk 'BEGIN{FS=","} /Jack/{print $0}' user.csv
Jack,male,20
匹配符(~)

匹配符(~)用来对 Record 中的特定字段使用正则表达式。!~ 表示不匹配。

$ cat data
This is line 1
Another line
line three
This is line four
$ gawk '$3 ~ /line/{print $0}' data
This is line 1
This is line four
$ gawk '$3 !~ /line/{print $0}' data
Another line
line three
数学表达式
$ cat user.csv
Jack,male,20
Rose,female,18
Mike,male,24
$ gawk 'BEGIN{FS=","} $3 >= 20{print $0}' user.csv
Jack,male,20
Mike,male,24
4. 结构化命令
if

if (condition) statement

$ cat numbers
2
4
6
8
10
$ gawk '{
> if ($1 < 5)
> {
> x = $1 - 2
> print x
> } else
> {
> x = $1 / 2
> print x
> }}' numbers
0
2
3
4
5
while
while (condition)
{
statements
}
cat number
130 120 135
160 113 140
145 170 215
$ gawk '{
> total = 0
> i = 1
> while (i <= 3)
> {
> total += $i
> i++
> }
> avg = total / 3
> print "Average:",avg
> }' number
Average: 128.333
Average: 137.667
Average: 176.667
for

for( variable assignment; condition; iteration process)

$ gawk '{
> total = 0
> for (i = 1; i < 4; i++)
> {
> total += $1
> }
> avg = total / 3
> print "Average:",avg
> }' number
Average: 130
Average: 160
Average: 145
5. 格式化输出

printf 命令格式:printf "format string", var1, var2 . . .

常用格式控制符如下表所示:

控制字符 描述
c 将数字显示为对应的 ASCII 字符
d 或 i 显示整数
e 将数字以科学记数法显示
f 显示浮点数
g 以科学计算法或浮点数显示(看哪种更短)
o 以八进制显示
s 显示字符串
x 以十六进制显示
X 以十六进制显示,使用大写的 A-F
$ gawk 'BEGIN{
> x = 10 * 100
> printf "The answer is: %e\n", x
> }'
The answer is: 1.000000e+03

控制字符以外,还可以使用另外三种修饰符以对输出进行更多的控制。

  • width :该数值用于指定输出的最小宽度。如长度不够,用空格补充
  • prec :该数值用于指定浮点数的精确度,或者字符串能包含字符的最大数量
  • -(减号):格式化输出时,使用左对齐
$ gawk 'BEGIN{FS="\n"; RS=""} {printf "%16s %s\n", $1, $4}' people.txt
Riley Mullen (312)555-1234
Frank Williams (317)555-9876
$
$ gawk 'BEGIN{FS="\n"; RS=""} {printf "%-16s %s\n", $1, $4}' people.txt
Riley Mullen (312)555-1234
Frank Williams (317)555-9876

参考下面的示例, %10.1f 中的 10 用于指定字段的最小宽度(右对齐,前面用空格补),.1 用于指定精确度。

$ gawk '{
> total = 0
> for (i = 1; i < 4; i++)
> {
> total += $i
> }
> avg = total / 3
> printf "Average: %10.1f\n",avg
> }' number
Average: 128.3
Average: 137.7
Average: 176.7
6. 内建函数
数学函数
函数 描述
atan2(x,y) x / y 的正切
cos(x) x 的余弦
exp(x) x 以 e 为底的指数
int(x) x 的整数部分
log(x) x 的自然对数
rand() 生成介于 0 和 1 之间的随机数
sin(x) x 的正弦
sqrt(x) x 的平方根
srand(x) 指定生成随机数的种子
$  gawk 'BEGIN{x=exp(100); print x}'
26881171418161356094253400435962903554686976
$ gawk 'BEGIN{x=exp(1000); print x}'
inf
字符串函数
函数 描述
gensub(r, s, h [, t]) 该函数用于检索字符串(默认为 $0 ,如 t 指定,则检索字符串 t),用正则表达式 r 进行匹配,并将匹配结果替换为 s 。如 h 为 "g" 或 "G" ,则执行全局替换;如 h 为数字,则只将第 h 个匹配项替换为 s
gsub(r, s [,t] 该函数用于检索字符串(默认为 $0 ,如 t 指定,则检索字符串 t),用正则表达式 r 进行匹配,并将匹配结果替换为 s (全局替换)
index(s, t) 该函数用于返回字符串 t 在字符串 s 中的位置索引(如 s 不包含 t ,则返回 0)
length([s]) 该函数用于返回字符串 s 的长度,如 s 未指定,则返回 $0 的长度
match(s, r ) 该函数用于返回字符串 s 中正则表达式 r 的位置索引
split(s, a [,r]) 该函数用于将字符串 s 根据 FS 符分割后的字段保存在数组 a 中。如已指定正则表达式 r ,则根据 r 而不是 FS 进行分割
sprintf(format, variablies) 该函数用于返回一个格式化后的字符串,该字符串类似 printf 函数的输出
sub(r, s [,t]) 该函数用于检索指定字符串 t (如果未指定 t ,则检索 $0),并使用 s 替换第一个符合条件的匹配结果
tolower(s) 将字符串 s 中的所有字符转换成小写
toupper(s) 将字符串 s 中的所有字符转换成大写
$ gawk 'BEGIN{
> x = "hello world, hello gawk, hello text"
> y = gensub("hello","nihao","g",x)
> print y}'
nihao world, nihao gawk, nihao text
$ gawk 'BEGIN{
> x = "hello world, hello gawk, hello text"
> y = gensub("hello","nihao",2,x)
> print y}'
hello world, nihao gawk, hello text
$
$ gawk 'BEGIN{
> x = "hello world, hello gawk, hello text"
> gsub("hello","nihao",x)
> print x}'
nihao world, nihao gawk, nihao text
$
$ gawk 'BEGIN{
> x = "hello world, hello gawk, hello text"
> split(x,var)
> print var[2] var[4] var[6]}'
world,gawk,text
$ gawk 'BEGIN{
> x = "hello world, hello gawk, hello text"
> split(x,var,",")
> print var[1] var[2] var[3]}'
hello world hello gawk hello text
时间函数
函数 描述
mktime(datespec) 将普通格式( YYYY MM DD HH MM SS )的时间日期转换成时间戳
strftime(format [,timestamp]) 将指定时间戳(如未指定,使用当前时间戳)转换成指定的时间日期格式
systime() 返回当前时间的时间戳
$ gawk 'BEGIN{
> date = systime()
> day = strftime("%A, %B %d, %Y", date)
> print day
> }'
Saturday, June 30, 2018
用户自定义函数

定义函数

function name([variables])
{
statements
}

使用函数

$ gawk '
> function myprint()
> {
> printf "%-16s - %s\n", $1, $4
> }
> BEGIN{FS="\n"; RS=""}
> {
> myprint()
> }' people.txt
Riley Mullen - (312)555-1234
Frank Williams - (317)555-9876

函数库

创建函数库

$ cat funclib
function myprint()
{
printf "%-16s - %s\n", $1, $4
}
function myrand(limit)
{
return int(limit * rand())
}
function printthird()
{
print $3
}

调用函数库

$ cat script
BEGIN{ FS="\n"; RS=""}
{
myprint()
}
$
$ gawk -f funclib -f script people.txt
Riley Mullen - (312)555-1234
Frank Williams - (317)555-9876

参考书籍

Linux Command Line and Shell Scripting Bible 3rd Edition

作者:rollingstarky
链接:https://www.jianshu.com/p/b46685e7bcbc
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

gawk使用方法简介的更多相关文章

  1. 网络神器Greasemonkey(油猴子)使用方法简介+脚本分享【转载】

    推荐下,觉得这个方法有用, 今天艾薇百科来介绍一下功能强大的Greasemonkey,俗称"油猴子",Greasemonkey可以自由定制网页,实现你想要的各种功能.堪称" ...

  2. Redis Cluster搭建方法简介22211111

    Redis Cluster搭建方法简介 (2013-05-29 17:08:57) 转载▼       Redis Cluster即Redis的分布式版本,将是Redis继支持Lua脚本之后的又一重磅 ...

  3. Monte Carlo方法简介(转载)

    Monte Carlo方法简介(转载)       今天向大家介绍一下我现在主要做的这个东东. Monte Carlo方法又称为随机抽样技巧或统计实验方法,属于计算数学的一个分支,它是在上世纪四十年代 ...

  4. C#——Marshal.StructureToPtr方法简介

    目录 MarshalStructureToPtr方法简介 功能及位置 语法 参数说明 异常 备注 举例 本博客(http://blog.csdn.net/livelylittlefish)贴出作者(三 ...

  5. TabBarController创建及使用方法简介

    TabBarController创建及使用方法简介 大致讲解一下TabBarController的创建过程: 首先,我们需要一些视图,如创建UIControllerView类型的view1,view2 ...

  6. delphi操作文本文件的方法简介

    delphi操作文本文件的方法简介减小字体 增大字体 作者佚名来源不详发布时间2008-5-31 10:31:16发布人xuedelphi1 文件类型和标准过程       Delphi同Object ...

  7. iOS中常用的四种数据持久化方法简介

    iOS中常用的四种数据持久化方法简介 iOS中的数据持久化方式,基本上有以下四种:属性列表.对象归档.SQLite3和Core Data 1.属性列表涉及到的主要类:NSUserDefaults,一般 ...

  8. jQuery的AJAX方法简介及与其他文件$符号冲突的解决办法

    一.重要的jQuery AJAX方法简介 $.load(url) 从服务器载入数据 $.get(url,callback) 从服务器请求数据,并执行回调函数 $.post(url,data,callb ...

  9. FragmentActivity与Fragment两者交互方法简介(转)

    FragmentActivity与Fragment两者交互方法简介 分类: Fragment 2014-07-07 18:17 88人阅读 评论(0) 收藏 举报 在Android4.0后很多时候我们 ...

随机推荐

  1. 5-21python数据类型

    一.字符串,是不可变数据类型,所有字符串的方法都不会修改字符串的值,使用字符串的方法后都是生成了一个新的字符串.就因为字符串是不可变变量! 字符串的方法 1. strip(),默认去空格,但是当()中 ...

  2. js简单化技巧

    1.交换两个变量而没有第三个 let x = 1;let y = 2;[x, y] = [y, x];console.log(x, y); 输出: 2 1 2.将数字转换为字符串 const num  ...

  3. jmeter 参数化学习之CSV Data Set Config随机读取一行参数

    需要使用到循环控制器,if控制器,CSV Data Set Config,Random Variable 4个组件 如图 先在线程组下面放一个随机数生成器 然后在同一层级设置一个永久的循环控制器,记住 ...

  4. PHP中的MySQLi扩展学习(二)mysqli类的一些少见的属性方法

    虽说是少见的一些属性方法,但是可能还是有不少同学在日常的开发中使用过,这里只是学习了可能相对来说我们用得比较少的一些 mysqli 的属性或方法.就当是扩展一下自己的知识体系. 切换用户 首先就是切换 ...

  5. Groovy系列(2)- Groovy与Java的不同之处

    Groovy与Java的不同之处 默认 imports 所有这些包和类都是默认导入的,不必使用显式import语句来使用它们 java.io.* java.lang.* java.math.BigDe ...

  6. 使用正则表达式在VS中批量移除 try-catch

    使用正则表达式在VS中批量移除 try-catch 前言 try-catch 意为捕获错误,一般在可能出错的地方使用(如调用外部函数或外部设备),以对错误进行正确的处理,并进行后续操作而不至于程序直接 ...

  7. jenkin—持续集成

    jenkins与持续集成 Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能.(百度百科) 持续集 ...

  8. Python中类-带括号与不带括号的区别

    类不带括号我们叫赋值,带括号我们叫实例化. 什么是赋值? a=7 b=a id(7) 140726814208448 id(a) 140726814208448 id(b) 1407268142084 ...

  9. session与cookie的联系与区别

    一.Session与Cookie介绍 这些都是基础知识,不过有必要做深入了解.先简单介绍一下. 二者的定义: 当你在浏览网站的时候,WEB 服务器会先送一小小资料放在你的计算机上,Cookie 会帮你 ...

  10. 通用JS9

    Symbol.toStringTag 该符号作为一个属性表示"一个字符串,该字符串用于创建对象的默认字符串描述."由内置方法Object.prototype.toString()使 ...