Linux:awk常用语法介绍
awk脚本的结构基本如下所示,awk脚本通常由3部分组成。BEGIN,END和带模式匹配选项的常见语句块。这3个部分都是可选项,在脚本中可省略任意部分:
awk ' BEGIN{ print "start" } pattern { commands } END{ print "end" } ' file
(2) 从文件或stdin中读取一行,然后执行pattern { commands }。重复这个过程,直到文件全部被读取完毕。
(3) 当读至输入流末尾时,执行END { commands } 语句块。
最重要的部分就是pattern语句块中的通用命令。这个语句块同样是可选的。如果不提供该语句块,则默认执行{ print },即打印所读取到的每一行。awk对于每一行,都会执行这个语句块。这就像一个用来读取行的while循环,在循环体中提供了相应的语句。每读取一行,awk就会检查该行和提供的样式是否匹配。样式本身可以是正则表达式、条件语句以及行匹配范围等。如果当前行匹配该样式,则执行{ }中的语句。样式是可选的。如果没有提供样式,那么awk就认为所有的行都是匹配的,并执行{ }中的语句。
通常将变量初始化语句(如var=0)以及打印文件头部的语句放入BEGIN语句块中。在END{}语句块中,往往会放入打印结果等语句。
qingsong@db2a:/tmp$ awk "BEGIN { i=0 } { i++ } END{ print i }" fil1.data
14
qingsong@db2a:/tmp$ wc -l fil1.data
14 fil1.data
示例2,打印文件
qingsong@db2a:/tmp$ awk {print} plainfile.txt
This is a file with plain text!
Hello,world
示例3,打印文件时加上头和尾:
qingsong@db2a:/tmp$ awk ' BEGIN { print "begin" } {print} END {print "end"}' plainfile.txt
begin
This is a file with plain text!
Hello,world
end
NF 当前行字段数
$0 当前行的文本
$1 当前行第一个字段
$n 当前n第n个字段
统计文件行数另一种办法:
$ awk 'END {print NR}' employee.txt
打印第2,4个字段
$ awk '{print $2,$4}' employee.txt
打印倒数第二个,倒数第一个字段:
$ awk '{print $(NF-1), $NF}' employee.txt
打印第4个字段,以及第4个字段加1000之后的值:
$ awk '{print $4, 1000+$4}' employee.txt
对第四个字段求和:
$ awk 'BEGIN{sum=0} {sum+=$4} END{print sum}' employee.txt
qingsong@db2a:/tmp$ var=1000
qingsong@db2a:/tmp$ echo | awk -v VARB=$var '{print VARB}'
传递多个变量:
qingsong@db2a:/tmp$ var1=abc
qingsong@db2a:/tmp$ var2=def
qingsong@db2a:/tmp$ echo | awk '{print v1, v2}' v1=$var1 v2=$var2
qingsong@db2a:/tmp$ awk 'NR < 3 {print $0}' employee.txt
行号等于2的号
qingsong@db2a:/tmp$ awk 'NR==2 {print $0}' employee.txt
等同于: sed -n '2p' employee.txt
第4列小于8800的行
qingsong@db2a:/tmp$ awk '$4 < 8800 {print $0}' employee.txt
包含Jason的行:
qingsong@db2a:/tmp$ awk '/Jason/ {print $0}' employee.txt
打印非空行
qingsong@db2a:/tmp$ awk '!/^$/ {print $0}' employee.txt
示例:打印系统中所有用户
qingsong@db2a:/tmp$ awk -F: '{print $1}' /etc/passwd
示例,打印每一行的长度:
qingsong@db2a:/tmp$ awk '{print length($0)}' employee.txt
打印非空行:
qingsong@db2a:/tmp$ awk 'length($0) > 0 {print $0}' employee.txt
就简单介绍到这么多,awk很复杂,也很强大,写起来能写一本书,我也不熟
awk脚本的结构基本如下所示,awk脚本通常由3部分组成。BEGIN,END和带模式匹配选项的常见语句块。这3个部分都是可选项,在脚本中可省略任意部分:
awk ' BEGIN{ print "start" } pattern { commands } END{ print "end" } ' file
awk命令的工作方式
(1) 执行BEGIN { commands } 语句块中的语句。(2) 从文件或stdin中读取一行,然后执行pattern { commands }。重复这个过程,直到文件全部被读取完毕。
(3) 当读至输入流末尾时,执行END { commands } 语句块。
最重要的部分就是pattern语句块中的通用命令。这个语句块同样是可选的。如果不提供该语句块,则默认执行{ print },即打印所读取到的每一行。awk对于每一行,都会执行这个语句块。这就像一个用来读取行的while循环,在循环体中提供了相应的语句。每读取一行,awk就会检查该行和提供的样式是否匹配。样式本身可以是正则表达式、条件语句以及行匹配范围等。如果当前行匹配该样式,则执行{ }中的语句。样式是可选的。如果没有提供样式,那么awk就认为所有的行都是匹配的,并执行{ }中的语句。
通常将变量初始化语句(如var=0)以及打印文件头部的语句放入BEGIN语句块中。在END{}语句块中,往往会放入打印结果等语句。
简单示例
示例1,使用awk统计文件行数qingsong@db2a:/tmp$ awk "BEGIN { i=0 } { i++ } END{ print i }" fil1.data
14
qingsong@db2a:/tmp$ wc -l fil1.data
14 fil1.data
示例2,打印文件
qingsong@db2a:/tmp$ awk {print} plainfile.txt
This is a file with plain text!
Hello,world
示例3,打印文件时加上头和尾:
qingsong@db2a:/tmp$ awk ' BEGIN { print "begin" } {print} END {print "end"}' plainfile.txt
begin
This is a file with plain text!
Hello,world
end
awk的特殊变量
NR 当前行号NF 当前行字段数
$0 当前行的文本
$1 当前行第一个字段
$n 当前n第n个字段
有以下文件:
qingsong@db2a:/tmp$ cat employee.txt
qingsong@db2a:/tmp$ cat employee.txt
Jason 32 M 8500
WuHong 35 F 9000
Miao 27 M 7500
统计文件行数另一种办法:
$ awk 'END {print NR}' employee.txt
打印第2,4个字段
$ awk '{print $2,$4}' employee.txt
打印倒数第二个,倒数第一个字段:
$ awk '{print $(NF-1), $NF}' employee.txt
打印第4个字段,以及第4个字段加1000之后的值:
$ awk '{print $4, 1000+$4}' employee.txt
对第四个字段求和:
$ awk 'BEGIN{sum=0} {sum+=$4} END{print sum}' employee.txt
传递变量
-v var=value assigns value to program variable var.qingsong@db2a:/tmp$ var=1000
qingsong@db2a:/tmp$ echo | awk -v VARB=$var '{print VARB}'
传递多个变量:
qingsong@db2a:/tmp$ var1=abc
qingsong@db2a:/tmp$ var2=def
qingsong@db2a:/tmp$ echo | awk '{print v1, v2}' v1=$var1 v2=$var2
条件过滤
行号小于3的行qingsong@db2a:/tmp$ awk 'NR < 3 {print $0}' employee.txt
行号等于2的号
qingsong@db2a:/tmp$ awk 'NR==2 {print $0}' employee.txt
等同于: sed -n '2p' employee.txt
第4列小于8800的行
qingsong@db2a:/tmp$ awk '$4 < 8800 {print $0}' employee.txt
包含Jason的行:
qingsong@db2a:/tmp$ awk '/Jason/ {print $0}' employee.txt
打印非空行
qingsong@db2a:/tmp$ awk '!/^$/ {print $0}' employee.txt
要打印出从M行到N行这个范围内的所有文本
$ awk 'NR==M, NR=N" filename
打印出start_pattern和end_pattern之间的文本
$ awk '/start_pattern/, /end_pattern/' filename
分割符
使用-F指定分割符示例:打印系统中所有用户
qingsong@db2a:/tmp$ awk -F: '{print $1}' /etc/passwd
内置字符串控制函数
只举一个例子,就是length(string),它返回字符串长度示例,打印每一行的长度:
qingsong@db2a:/tmp$ awk '{print length($0)}' employee.txt
打印非空行:
qingsong@db2a:/tmp$ awk 'length($0) > 0 {print $0}' employee.txt
就简单介绍到这么多,awk很复杂,也很强大,写起来能写一本书,我也不熟