简介
awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。
awk有3个不同版本: awk、nawk和gawk,未作特别说明,一般指gawk,gawk 是 AWK 的 GNU 版本。
二、语法
awk '{pattern + action}' {filenames}
pattern 表示 AWK 在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列命令。中括号({})不是必须的,但它们用于根据特定的模式对一系列指令进行分组。 pattern就是要表示的正则表达式,用斜杠括起来。awk语言的最基本功能是在文件或者字符串中基于指定规则浏览和抽取信息,awk抽取信息后,才能进行其他文本操作。完整的awk脚本通常用来格式化文本文件中的信息。
通常,awk是以文件的一行为处理单位的。awk每接收文件的一行,然后执行相应的命令,来处理文本。
[root@HikvisionOS test]# awk --help
Usage: awk [POSIX or GNU style options] -f progfile [--] file ...
Usage: awk [POSIX or GNU style options] [--] 'program' file ...
POSIX options: GNU long options: (standard)
-f progfile --file=progfile
-F fs --field-separator=fs
-v var=val --assign=var=val
Short options: GNU long options: (extensions)
-b --characters-as-bytes
-c --traditional
-C --copyright
-d[file] --dump-variables[=file]
-e 'program-text' --source='program-text'
-E file --exec=file
-g --gen-pot
-h --help
-L [fatal] --lint[=fatal]
-n --non-decimal-data
-N --use-lc-numeric
-O --optimize
-p[file] --profile[=file]
-P --posix
-r --re-interval
-S --sandbox
-t --lint-old
-V --version
To report bugs, see node `Bugs' in `gawk.info', which is
section `Reporting Problems and Bugs' in the printed version.
gawk is a pattern scanning and processing language.
By default it reads standard input and writes standard output.
Examples:
gawk '{ sum += $1 }; END { print sum }' file
gawk -F: '{ print $1 }' /etc/passwd
调用 awk
1.命令行方式
awk [-F field-separator] 'commands' input-file(s)
其中,commands 是真正awk命令,[-F域分隔符]是可选的。 input-file(s) 是待处理的文件。
在awk中,文件的每一行中,由域分隔符分开的每一项称为一个域。通常,在不指名-F域分隔符的情况下,默认的域分隔符是空格。
2.shell脚本方式
将所有的awk命令插入一个文件,并使awk程序可执行,然后awk命令解释器作为脚本的首行,一遍通过键入脚本名称来调用。
相当于shell脚本首行的:#!/bin/sh
可以换成:#!/bin/awk
3.将所有的awk命令插入一个单独文件,然后调用:
awk -f awk-script-file input-file(s)
其中,-f选项加载awk-script-file中的awk脚本,input-file(s)跟上面的是一样的。
awk内置变量
awk有许多内置变量用来设置环境信息,这些变量可以被改变,下面给出了最常用的一些变量。
ARGC 命令行参数个数 ARGV 命令行参数排列 ENVIRON 支持队列中系统环境变量的使用 FILENAME awk浏览的文件名 FNR 浏览文件的记录数 FS 设置输入域分隔符,等价于命令行 -F选项 NF 浏览记录的域的个数 NR 已读的记录数 OFS 输出域分隔符 ORS 输出记录分隔符 RS 控制记录分隔符
print和printf
awk中同时提供了print和printf两种打印输出的函数。
其中print函数的参数可以是变量、数值或者字符串。字符串必须用双引号引用,参数用逗号分隔。如果没有逗号,参数就串联在一起而无法区分。这里,逗号的作用与输出文件的分隔符的作用是一样的,只是后者是空格而已。
printf函数,其用法和c语言中printf基本相似,可以格式化字符串,输出复杂时,printf更加好用,代码更易懂。
运算符
内建变量
示例:
2 This is,the first.line,1
4 That,is the.second line,2
5 They is,the third,line.3
7 ME is,the fourth.4
输出文件的名称和大小以M为单位:
ls -l |awk 'BEGIN {size=0;} {size=size+$5;printf "%-6s %-6s %-6s\n", $9,size/1024,"kb"}'
[root@HikvisionOS test]# ls -al
总用量 16
drwxrwxrwx 2 root root 49 12月 25 14:42 .
drwxr-xr-x 6 root root 4096 12月 24 14:58 ..
-rwxrwxrwx 1 root root 51 12月 25 10:23 1111
-rwxrwxrwx 1 root root 1506 12月 24 16:20 service.sh
-rwxrwxrwx 1 root root 103 12月 25 14:42 text.txt
[root@HikvisionOS test]# ls -l |awk 'BEGIN {size=0;} {size=size+$5;printf "%-6s %-6s %-6s\n", $9,size/1024,"kb"}'
0 kb
1111 0.0498047 kb
service.sh 1.52051 kb
text.txt 1.62109 kb
以.为分割符输出文件处理之后的第一列数据:
awk 'BEGIN{FS="."} {print $1}' text.txt
awk -F . '{print $1}' text.txt
awk -F ‘.’ '{print $1}' text.txt
[root@HikvisionOS test]# awk -F . '{print $1}' text.txt
2 This is,the first
4 That,is the
5 They is,the third,line
7 ME is,the fourth
比较运算: >、==、<、<=等;变量定义 -v
变量定义运算:
awk -v a=2 -v b=-s '{printf "%d %s\n", $1+a, $2b}' text.txt
awk -va=2 -vb=-s '{printf "%d %s\n", $1+a, $2b}' text.txt
[root@HikvisionOS test]# awk -v a=2 -v b=-s '{printf "%d %s\n", $1+a, $2b}' text.txt
4 This-s
6 That,is-s
7 They-s
9 ME-s
[root@HikvisionOS test]# awk -va=2 -vb=-s '{printf "%d %s\n", $1+a, $2b}' text.txt
4 This-s
6 That,is-s
7 They-s
9 ME-s
输出首行数字大于3的数据:
awk '$1 > 3' text.txt
awk '$1>3 {print $1}' text.txt
[root@HikvisionOS test]# awk '$1 > 3' text.txt
4 That,is the.second line,2
5 They is,the third,line.3
7 ME is,the fourth.4
[root@HikvisionOS test]#
/[word]/ 表示模式配(~ 表示模式开始);! 表示非运算;&& 表示且运算;== 表示判断(字母时需要用双引号起来);=表示赋值/替换操作; | 模式匹配(/word|word/)的或运算; ^ 模式匹配值中表示列以特定要求开头。$模式匹配值中表示列以特定要求结束
输出包含指定字符串的数据:
awk '/Th/' text.txt
[root@HikvisionOS test]# awk '/Th/' text.txt
2 This is,the first.line,1
4 That,is the.second line,2
5 They is,the third,line.3
[root@HikvisionOS test]#
输出不包含指定字符串的数据:
awk '!/Th/' text.txt
[root@HikvisionOS test]# awk '!/Th/' text.txt
7 ME is,the fourth.4
[root@HikvisionOS test]# awk '/Th/ {print $1, $2}' text.txt
2 This
4 That,is
5 They
[root@HikvisionOS test]#
> 和 == 比较操作
[root@HikvisionOS test]# awk '$1>3 && $1==5 {print $1, $2}' text.txt
5 They
[root@HikvisionOS test]# awk '$1>3 && $2=="ME" {print $1, $2}' text.txt
7 ME
[root@HikvisionOS test]#
= 赋值/替换操作
[root@HikvisionOS test]# awk '$1>3 && $2="fgoiafido" {print $1, $2}' text.txt
4 fgoiafido
5 fgoiafido
7 fgoiafido
[root@HikvisionOS test]# awk '$1>3 && $2=5 {print $1, $2}' text.txt
4 5
5 5
7 5
[root@HikvisionOS test]#
取反操作
[root@HikvisionOS test]# awk '$2 ~ /Th/ {print $1,$2}' text.txt
2 This
4 That,is
5 They
[root@HikvisionOS test]# awk '$2 !~ /Th/ {print $1,$2}' text.txt
7 ME
| 模式匹配的或运算
[root@HikvisionOS test]# awk '$2 ~ /^Tha|^Thi/ {print $1,$2}' text.txt
2 This
4 That,is
列^(开始)、$(结束)匹配
[root@HikvisionOS test]# awk '$2 ~ /^Thi/ {print $1,$2}' text.txt
2 This
[root@HikvisionOS test]# awk '$2 ~ /is$/ {print $1,$2}' text.txt
2 This
4 That,is
[root@HikvisionOS test]#
忽略大小写
awk 'BEGIN{IGNORECASE=1} /this/' test
[root@HikvisionOS test]# awk 'BEGIN{IGNORECASE=1} /this/' text.txt
2 This is,the first.line,1
awk脚本
awk -f file.awk test
关于awk脚本,需要注意BEGIN和END两个关键词:
(1)BEGIN{存放执行前的语句};
(2)END{存放处理完所有的行后要执行的语句}。
例如:
现有数据如下:
我们的awk脚本内容如下:
执行结果如下:
条件语句
awk中的条件语句是从C语言中借鉴来的,见如下声明方式:
if (expression) {
statement;
statement;
... ...
}if (expression) {
statement;
} else {
statement2;
}if (expression) {
statement1;
} else if (expression1) {
statement2;
} else {
statement3;
}
循环语句
awk中的循环语句同样借鉴于C语言,支持while、do/while、for、break、continue,这些关键字的语义和C语言中的语义完全相同。
数组
因为awk中数组的下标可以是数字和字母,数组的下标通常被称为关键字(key)。值和关键字都存储在内部的一张针对key/value应用hash的表格里。由于hash不是顺序存储,因此在显示数组内容时会发现,它们并不是按照你预料的顺序显示出来的。数组和变量一样,都是在使用时自动创建的,awk也同样会自动判断其存储的是数字还是字符串。一般而言,awk中的数组用来从记录中收集信息,可以用于计算总和、统计单词以及跟踪模板被匹配的次数等等。