前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Linux三大剑客之awk

Linux三大剑客之awk

作者头像
耕耘实录
发布2018-12-20 14:47:36
1K0
发布2018-12-20 14:47:36
举报
文章被收录于专栏:耕耘实录耕耘实录

版权声明:本文为耕耘实录原创文章,各大自媒体平台同步更新。欢迎转载,转载请注明出处,谢谢

一、概述

awk的名称来源于其最初设计者Alfred V. Aho, Peter J. Weinberger, and Brian W. Kernighan的姓氏。awk最原始的版本是1977年在AT&T贝尔实验室诞生的,awk经过改进生成的新的版本nawk,gawk,现在默认linux系统下日常使用的是gawk。我目前使用的操作系统为CentOS Linux release 7.2.1511,系统自带的awk版本为:GNU awk 4.0.2。

二、awk的用途
  • 文本处理。
  • 格式化输出文本、报告。
  • 数字运算(在我之前的文章中,探讨过整数的算术运算,浮点运算可以使用awk)。
  • 执行字符串操作。
三、系统内几个有关awk命令的区别与联系

通过命令,我们可以看到:

代码语言:javascript
复制
[awk@GeekDevOps ~]$ ls -l /bin/*awk
lrwxrwxrwx. 1 root root      4 11月 20 10:41 /bin/awk -> gawk
-rwxr-xr-x. 1 root root 514136 6月  10 2014 /bin/dgawk
-rwxr-xr-x. 1 root root 428576 6月  10 2014 /bin/gawk
-rwxr-xr-x. 1 root root   3188 6月  10 2014 /bin/igawk
-rwxr-xr-x. 1 root root 428600 6月  10 2014 /bin/pgawk

与awk有关的命令竟然有这么多!在用whatis命令看一下这些都是些什么鬼:

代码语言:javascript
复制
[awk@GeekDevOps ~]$ whatis awk gawk dgawk pgawk igawk
awk (1)              - pattern scanning and processing language
gawk (1)             - pattern scanning and processing language
dgawk (1)            - pattern scanning and processing language
pgawk (1)            - pattern scanning and processing language
igawk (1)            - gawk with include files

不太确信以上结果,我又使用man、info挨个看了一下,结果awk、gawk、dgawk、pgawk都是gawk,在线手册一模一样。唯独igawk与前面四个不太一样,是包含文件的gawk,其实也是gawk。awk是gawk的一个软连接,大家都是gawk!

四、awk的使用
4.1 理解awk的工作原理
image
image

Read

awk从输入流(文件,管道或者标准输入)中读取一行,然后存储到内存中。

Execute

所有的AWK命令都依次在输入文本上执行。默认情况下,awk会对每一行执行命令,可以通过提供模式限制这种行为。

Repeat

处理过程不断重复,从首行开始直到到达文件结尾。

创建marks.txt文件备用:

代码语言:javascript
复制
[awk@GeekDevOps ~]$ echo "1)  Amit    Physics  80
> 2)  Rahul   Maths    90
> 3)  Shyam   Biology  87
> 4)  Kedar   English  85
> 5)  Hari    History  89">marks.txt
4.2 awk的结构

BEGIN 语句块

BEGIN语句块的语法:

代码语言:javascript
复制
BEGIN {awk-commands}

BEGIN语句块在程序开始的使用执行,只执行一次,在这里可以初始化变量。BEGIN是AWK的关键字,因此它必须为大写。注意,这个语句块是可选的。

BODY 语句块

BODY语句块的语法:

代码语言:javascript
复制
/pattern/ {awk-commands}

BODY语句块中的命令会对输入的每一行执行,也可以通过提供模式来控制这种行为。注意,BODY语句块没有关键字。

END 语句块

END语句块的语法:

代码语言:javascript
复制
END {awk-commands}

END语句块在程序的最后执行,END是AWK的关键字,因此必须为大写,它也是可选的。

结合以上2点,举个例子来理解一下:

代码语言:javascript
复制
[awk@GeekDevOps ~]$ awk BEGIN'{printf "Sr NO\tName\tSub\tMarks\n"} {print} END{print "Done!"}' marks.txt
Sr NO   Name    Sub     Marks
1)  Amit    Physics  80
2)  Rahul   Maths    90
3)  Shyam   Biology  87
4)  Kedar   English  85
5)  Hari    History  89
Done!
[awk@GeekDevOps ~]$ awk BEGIN'{printf "Sr NO\tName\tSub\tMarks\n"} END{print "Done!"}' marks.txt
Sr NO   Name    Sub     Marks
Done!

在本例中,BEGIN块被执行一次,给文本内容增加了一行标题。body块从文本第一行扫描直至文件末尾。END块也仅仅执行了一次。

4.3 使用awk

通常情况下,awk命令较简短时我们直接按照以下方式执行awk命令:

代码语言:javascript
复制
awk 'program' input-file1 input-file2 …

如果awk内容较多的话,我们以以下格式来执行awk命令(此处program-file为awk脚本内容):

代码语言:javascript
复制
awk -f program-file input-file1 input-file2 …

awk是一门解释型的语言,所以也可以像执行bash shell一样执行awk脚本:

代码语言:javascript
复制
#!/bin/awk -f
BEGIN{print "My name is Ivan Du!"}
代码语言:javascript
复制
[awk@GeekDevOps ~]$ chmod u+x GeekDevOps.awk
[awk@GeekDevOps ~]$ ./GeekDevOps.awk
My name is Ivan Du!
4.4 打印某列或某字段
代码语言:javascript
复制
[awk@GeekDevOps ~]$ cat best.txt
www     CC      ICBC
[awk@GeekDevOps ~]$ awk '{print $1}' best.txt
www
[awk@GeekDevOps ~]$ awk '{print $3}' best.txt
ICBC
[awk@GeekDevOps ~]$ awk -F "\t" '{print $3}' best.txt
ICBC

默认情况下,awk以空格、制表符等符号为分隔符。从每一行的第一个字符串开始扫描,第一个字符串为1,第N个字符串为1,第N个字符串为1,第N个字符串为n,如果首行是空格之类的字符那也算。

4.5 打印匹配模式的列

当模式匹配成功时,默认情况下awk会打印该行,但是也可以让它只打印指定的字段。例如,下面的例子中,只会打印出匹配模式的第三和第四个字段。

代码语言:javascript
复制
[awk@GeekDevOps ~]$ awk '/a/ {print $3 " " $4}' marks.txt
Maths 90
Biology 87
English 85
History 89

匹配指定文件中带u的行,并打印第四列与第三列,中间以一个横向制表符隔开。

代码语言:javascript
复制
[awk@GeekDevOps ~]$ awk '/u/ {print $4"\t"$3}' marks.txt
90      Maths
4.6 统计文本总行数
代码语言:javascript
复制
[awk@GeekDevOps ~]$ awk 'BEGIN{ct=0} {++ct} END{print "Count:",ct}' marks.txt
Count: 5

此行命令中,BEGIN部分其实是可以省略的。

4.7 打印匹配模式的总行数
代码语言:javascript
复制
[awk@GeekDevOps ~]$ awk '/a/ {++ct} END{print "Count:",ct}' marks.txt
Count: 4

此处的BEGIN部分不能出现,否则报错。

4.8 打印超过指定长度的行
代码语言:javascript
复制
[awk@GeekDevOps ~]$ awk 'length($0) > 22' marks.txt
1)  Amit    Physics  80
2)  Rahul   Maths    90
3)  Shyam   Biology  87
4)  Kedar   English  85
5)  Hari    History  89

mark.txt文件是通过空格来控制对齐的,每一行加上空格一共是22个字符。

4.9 ARGC命令行参数个数
代码语言:javascript
复制
[awk@GeekDevOps ~]$ awk 'BEGIN{print "Arguments=" ARGC}' One Two Three Four
Arguments=5
4.10 ARGV命令行参数数组
代码语言:javascript
复制
[awk@GeekDevOps ~]$ awk 'BEGIN{for (i=0 ;i<ARGC-1;++i ){printf "ARGC[%d]=%s\n",i,ARGV[i]}}' One Two Three Four
ARGC[0]=awk
ARGC[1]=One
ARGC[2]=Two
ARGC[3]=Three
4.11 ENVIRON环境变量
代码语言:javascript
复制
[awk@GeekDevOps ~]$ awk 'BEGIN{print ENVIRON["PATH"]}'
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/awk/.local/bin:/home/awk/bin
4.12 FILENAME当前文件名
代码语言:javascript
复制
[awk@GeekDevOps ~]$ awk 'END{print FILENAME}' marks.txt 
marks.txt

注意:此处使用的是END,如果省略则会打印出5个文件名称,这个文件一5行。

4.13 常用的awk内置变量

变量名

属性

$0

当前记录

1−1−1-n

当前记录的第N个字段

FS

读入字段的分隔符,默认为空格

RS

读入记录分隔符,默认为换行符

NF

列,当前记录中的字段个数

NR

行,已经读出的行数,也就是行号

OFS

输出字段分隔符,默认为空格

ORS

输出记录分隔符,默认为换行符

代码语言:javascript
复制
[awk@GeekDevOps ~]$ awk -F " " '{print $4}' marks.txt 
80
90
87
85
89
[awk@GeekDevOps ~]$ awk '{print $3}' marks.txt 
Physics
Maths
Biology
English
History
[awk@GeekDevOps ~]$ awk 'BEGIN{FS=" "}{print $3}' marks.txt 
Physics
Maths
Biology
English
History

以上三种写法都是一样的效果。

代码语言:javascript
复制
[awk@GeekDevOps ~]$ ls -al | awk 'BEGIN{size=0}{size+=$5}END{print size/1024/1024 "MB"}'
128.017MB
[awk@GeekDevOps ~]$ ls -al|awk 'NR>1{size+=$5} END{print size/1024/1024 "MB"}'
128.017MB
代码语言:javascript
复制
[awk@GeekDevOps ~]$ ls -al|awk 'NR==1{print $2/1024 "MB"}'
128.035MB

以上两个代码片中,都是统计当前目录下所有的文件(包括隐藏文件)所占磁盘空间的大小,非常有用。

代码语言:javascript
复制
[awk@GeekDevOps ~]$ awk 'BEGIN{print "OFS=" OFS}' marks.txt
OFS=
4.14 awk中的算术运算

在awk中,支持像C语言中一样的算术运算。在前面的文章中介绍过,Linux系统中无法对非整型数字直接进行算术运算,要对浮点型的数据就行算术运算我们可以使用awk来实现。

代码语言:javascript
复制
[awk@GeekDevOps ~]$ awk 'BEGIN{A=2.8;B=7;print A/B}'
0.4

在这一部分中,awk中的增减运算符、赋值运算符、关系操作符、逻辑运算符、三元操作符等均与C语言类似,不赘述。

4.15 awk中的一元操作符
代码语言:javascript
复制
[awk@GeekDevOps ~]$ awk 'BEGIN{A=2.8;A=+A;print A}'
2.8
4.16 awk中的指数操作符
代码语言:javascript
复制
[awk@GeekDevOps ~]$ awk 'BEGIN{A=2.8;A=A^3;print A}'
21.952
[awk@GeekDevOps ~]$ awk 'BEGIN{A=2.8;A=A**3;print A}'
21.952
4.17 awk中的字符串连接操作符
代码语言:javascript
复制
[awk@GeekDevOps ~]$ awk 'BEGIN{str1="Hello";str2=",GeekDevOps";str3=str1 str2;print str3}'
Hello,GeekDevOps
4.18 awk中的数组

数组的定义与C语言有类似的地方,也有差别,使用的时候需要注意一下,有的资料上说awk中不支持多维数组,通过awk的GUN的文档,我们可以看到,awk也是支持多维数组的。删除数组元素使用delete语句:

代码语言:javascript
复制
[awk@GeekDevOps ~]$ awk 'BEGIN{array[0][0]=2;array[0][1]=3;array[1][0]=4;array[1][1]=8;for(i=0;i<2;i++){for(j=0;j<2;j++){printf "array[%d][%d]=%d\n",i,j, array[i][j]}}delete array[0][0];print array[0][0] "\t" array[0][0]}'
array[0][0]=2
array[0][1]=3
array[1][0]=4
array[1][1]=8
4.19 awk中的控制结构

在awk中,也支持类似C语言一样的程序结构,支持if-else、while、do-while、for、switch、break、continue、nex、nextfile、exit。相信很多小伙伴都学习过C语言,与C语言一样的就不在赘述。

代码语言:javascript
复制
[awk@GeekDevOps ~]$ awk 'NF != 4 {
    printf("%s:%d: skipped: NF != 4\n", FILENAME, FNR) > "/dev/stderr"
    next
}'

-:1: skipped: NF != 4

-:2: skipped: NF != 4
...
代码语言:javascript
复制
[awk@GeekDevOps ~]$ awk 'BEGIN {
    if (("date" | getline date_now) <= 0) {
        print "Can not get system date" > "/dev/stderr"
        exit 1
    }
    print "Current date is", date_now
    close("date")
}'
Current date is 2018年 02月 28日 星期三 23:05:16 CST
4.20 awk中的函数

在awk中,支持内建函数与用户自定义函数。

常用数学计算函数

atan2(y, x)

代码语言:javascript
复制
Return the arctangent of y / x in radians. You can use ‘pi = atan2(0, -1)’ to retrieve the value of pi.

cos(x)

代码语言:javascript
复制
Return the cosine of x, with x in radians.

exp(x)

代码语言:javascript
复制
Return the exponential of x (e ^ x) or report an error if x is out of range. The range of values x can have depends on your machine’s floating-point representation.

int(x)

代码语言:javascript
复制
Return the nearest integer to x, located between x and zero and truncated toward zero. For example, int(3) is 3, int(3.9) is 3, int(-3.9) is -3, and int(-3) is -3 as well.

log(x)

代码语言:javascript
复制
Return the natural logarithm of x, if x is positive; otherwise, return NaN (“not a number”) on IEEE 754 systems. Additionally, gawk prints a warning message when x is negative.

rand()

代码语言:javascript
复制
Return a random number. The values of rand() are uniformly distributed between zero and one. The value could be zero but is never one.

sin(x)

代码语言:javascript
复制
Return the sine of x, with x in radians.

sqrt(x)

代码语言:javascript
复制
Return the positive square root of x. gawk prints a warning message if x is negative. Thus, sqrt(4) is 2.

srand([x])

代码语言:javascript
复制
Set the starting point, or seed, for generating random numbers to the value x. 

字符串函数

代码语言:javascript
复制
asort(arr [, d [, how] ])
asorti(arr [, d [, how] ])
gsub(regex, sub, string)
index(str, sub)
length(str)
match(str, regex)
split(str, arr, regex)
sprintf(format, expr-list)
strtonum(str)
sub(regex, sub, string)
substr(str, start, l)
tolower(str)
toupper(str)

时间函数

代码语言:javascript
复制
systime
mktime(datespec)
strftime([format [, timestamp[, utc-flag]]])

字节操作函数

代码语言:javascript
复制
and
compl
lshift
rshift
or
xor

自定义函数类似于C语言,参阅GUN网站function部分。

4.21 awk中的正则表达式
代码语言:javascript
复制
[awk@GeekDevOps ~]$ echo -e "My name is IVAN DU.\nMy blog is GeekDevOps.\nWelcome to my blog."|awk '/My+/'
My name is IVAN DU.
My blog is GeekDevOps.
[awk@GeekDevOps ~]$ echo -e "My name is IVAN DU.\nMy blog is GeekDevOps.\nWelcome to my blog."|awk '/^W/'
Welcome to my blog.
五、参考资料

https://www.tutorialspoint.com/awk/index.htm https://www.gnu.org/software/gawk/manual/gawk.html https://en.wikipedia.org/wiki/AWK#Sum_last_word

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年03月01日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、概述
  • 二、awk的用途
  • 三、系统内几个有关awk命令的区别与联系
  • 四、awk的使用
    • 4.1 理解awk的工作原理
      • 4.2 awk的结构
        • 4.3 使用awk
          • 4.4 打印某列或某字段
            • 4.5 打印匹配模式的列
              • 4.6 统计文本总行数
                • 4.7 打印匹配模式的总行数
                  • 4.8 打印超过指定长度的行
                    • 4.9 ARGC命令行参数个数
                      • 4.10 ARGV命令行参数数组
                        • 4.11 ENVIRON环境变量
                          • 4.12 FILENAME当前文件名
                            • 4.13 常用的awk内置变量
                              • 4.14 awk中的算术运算
                                • 4.15 awk中的一元操作符
                                  • 4.16 awk中的指数操作符
                                    • 4.17 awk中的字符串连接操作符
                                      • 4.18 awk中的数组
                                        • 4.19 awk中的控制结构
                                          • 4.20 awk中的函数
                                            • 4.21 awk中的正则表达式
                                            • 五、参考资料
                                            领券
                                            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档