awk
awk是最有用的shell工具之一,名字的来源是三位工程师的名字首字母。
awk introduction
awk主要被用在文字和字符处理领域,作为一个通用的可编程过滤器。
awk面向域(field)而sed面向行(line),awk支持以文件、重定向、管道和标准输入作为程序的输入。
更准确的来讲,awk是一种仅需几行代码就能够处理复杂任务的编程语言,和sed一样,它是一种pattern-action语言,看起来和C语言类似,但是比C语言简单,它能够自动处理输入、域分割、初始化和内存管理等。
awk相比较于sed的特色:
- 方便的数字处理
- 在action中的变量和控制流
- 更便于访问行中的域
- 灵活的输出
- 内置丰富的算术和字符串函数
- 类C风格
awk的程序结构
一段awk程序包括:
- 一段可选的BEGIN语句块(主要用于做一些预处理)
- 一些pattern-action组合
- 一段可选的END语句块(主要用于做一些后处理)
1 | BEGIN {action} |
有几种方式运行一段awk程序:
a. awk ‘program’ input_files
b. awk ‘program’ 标准输入作为程序输入
c. awk -f ‘program_files’ input_files
pattern & action
awk从一系列输入文件中去搜索指定的pattern,然后执行特定的action当在遇到包含特定pattern的行或者域。
awk不会修改输入文件,一次只处理一行。
一个awk程序至少有一个pattern或者action
- 默认的pattern是匹配所有的lines
- 默认的action是打印当前的record
- action包含在{}内,而pattern直接列出。
patterns
pattern是一个决定是否后面action是否被执行的选择器。
pattern可以是:
- 特殊测token,例如BEGIN和END
- 正则表达式 包含在//里面 例如 /[a-z]/
- 字符串匹配表达式
- !表达式取反
- 以及通过&& 、|| 链接符连接的上述任意表达式
- /NYU/
- x > 0
- /NYU/ && (name == ‘UNIX Tools’)
特殊的pattern token
- BEGIN:预处理,常用于初始化一些内置变量例如FS、RS等;
- END:后处理
actions
action可能包含一系列的类C的代码语句,执行一些类似算术、字符串表达式、声明以及输出。
action当每一行匹配一个pattern就会被执行,如果不指定pattern,action无条件执行,如果action不被指定,默认action是输出到标准设备。
例子:
1 | ls|awk 'BEGIN {print "List all C language source files."} |
varaibles
作为一门语言,那么awk脚本当然可以定义和使用变量。
例如:
1 | BEGIN {sum = 0} |
后面会介绍到,awk预定义了一些有用变量。
records
预定义变量:
- RS Record Separator
- NR Number of Records
默认record seprator是newline,默认的awk一次处理一行。
RS可以是任意正则表达式,可以在BEGIN action中更改。
1 | cat temp.txt|awk '{print "#"NR, $0}' |
上面的$0表示该记录的第0个域,$开头的数字变量都表示域编号。
fields
预定义变量:
- NF:Number of Field
- FS:Filed Separator
输入中的每一行都按域分隔符被拆分。
- awk预定义变量FS Filed Separator默认是空格(一个或多个空格或者tab)
- awk -Fc可以设置FS为字符c
- $0是当前所有行
- $1是第一个域….,$NF是最后一个域,以此类推
- {print $(NF-2)} 倒数第三个域
- 计算和打印
- {print $1, $2*$3}
默认的由”,”连接的项会被print打印为由单个空格连接的项。
格式化输出:
- printf(fmt, val1, val2, …)
- {printf(“%-8s %6.2f\n”, $1, $2)}
selectoins
前面提到awk是用作一个可编程的过滤器,用于处理文本和字符串。
除了前面提到的pattern(正则、begin&end等),更有用的的awk pattern还可以是如下这样的表达式pattern:
- 比较: $2 >= 50 {print}
- 计算: $2 * $3 > 50 {printf(“%6.2f “, $1)}
- 文本内容:
- $1 == “NYU”
- $2 ~ /NYU/
- 模式组合: $2 >= 4 || $3 >= 20
- 行号 NR >= 10 && NR <= 20
- ….
computings
awk可以方便的对域进行一些基本的计算,例如:
- counting
1 | $3 > 15 {emp = emp + 1} |
- average and sum
1 | {pay = pay + $2 * $3} |
strings manipulation
awk内置一些函数,用于处理字符串。
- length(s)
- substr(s,m,n)
1 | {nc = nc + length($0) + 1 |
control flow
awk作为一门编程语言,提供几种基本的类C的流程控制结构。
- IF THEN ELSE结构
1 | $2 > 6 { n = n + 1} |
- WHILE
- DO WHILE
- FOR
1 | for (i = 1; i < 10; i = i + 1) |
array
- array下标可以是数字和字符串,当下标是字符串的时候,可以当一个map使用
- example:a[“tom”] = 0.3
数组遍历:
1 | for (k in array) { |
awk predefined variales
- $0 $1 $2 $NF
- NF NR NF
- FS RS
- FILENAME
- OFS:output field separator default is single space
built-in functions
- arithmetic
- sin, cos, tan, exp, log, sqrt
- strings
- length, substr, split
- output
- print, printf
- special
- system(“cmd”) eg: system(“clear”)
- exit -直接跳转到ENDpattern-action块
code snippets
- filter blank lines while you want to count your code
1 | cat /path/to/yourcode/*.py | awk NF | wc -l |
因为NF表示Number of Filed,默认的FS为空格,当awk遇见空行的时候,作为pattern的NF值为0,因此该行不会被输出。