awk -F fs 'BEGIN{ } /pattern/ {action} END{ }' input-file ;-F 是指定分隔符
awk [选项参数] 'script' var=value file(s)
或
awk [选项参数] -f scriptfile var=value file(s)
= += -= = /= %= = *= 赋值
?: C 条件表达式
|| 逻辑或
&& 逻辑与
~ ~! 匹配正则表达式和不匹配正则表达式
< <= > >= != == 关系运算符
空格 连接
shell
# 输出包含"re" 的行
$ awk '/re/ ' log.txt
---------------------------------------------
3 Are you like awk
10 There are orange,apple,mongo
关系表达式:使用运算符进行操作,可以是字符串或数字的比较测试
操作由一个或多个命令、函数、表达式组成,之间由换行符或分号隔开,并位于大刮号内,主要部分是:变量或数组赋值、输出命令、内置函数、控制流语句。
BEGIN 语句块, pattern 语句块, END 语句块
awk 'BEGIN{ commands } pattern{ commands } END{ commands }' file
awk 脚本通常由 BEGIN, 通用语句块,END 语句块组成,三部分都是可选的。 脚本通常是被单引号或双引号包住。
BEGIN{ 这里面放的是执行前的语句 }
END {这里面放的是处理完所有的行后要执行的语句 }
{这里面放的是处理每一行时要执行的语句}
例子 1:
awk 'BEGIN{ i=0 } { i++ } END{ print i }' filename
例子 2:
假设有这么一个文件(学生成绩表):
$ cat score.txt
Marry 2143 78 84 77
Jack 2321 66 78 45
Tom 2122 48 77 71
Mike 2537 87 97 95
Bob 2415 40 57 62
脚本:
$ touch cal.awk
awk -f
#运行前
BEGIN {
math = 0
english = 0
computer = 0
printf "NAME NO. MATH ENGLISH COMPUTER TOTAL\n"
printf "---------------------------------------------\n"
}
#运行中
{
math+=$3
english+=$4
computer+=$5
printf "%-6s %-6s %4d %8d %8d %8d\n", $1, $2, $3,$4,$5, $3+$4+$5
}
#运行后
END {
printf "---------------------------------------------\n"
printf " TOTAL:%10d %8d %8d \n", math, english, computer
printf "AVERAGE:%10.2f %8.2f %8.2f\n", math/NR, english/NR, computer/NR
}
运行结果
$ awk -f cal.awk score.txt
NAME NO. MATH ENGLISH COMPUTER TOTAL
---------------------------------------------
Marry 2143 78 84 77 239
Jack 2321 66 78 45 189
Tom 2122 48 77 71 196
Mike 2537 87 97 95 279
Bob 2415 40 57 62 159
---------------------------------------------
TOTAL: 319 393 350
AVERAGE: 63.80 78.60 70.00
变量 描述
$n 当前记录的第 n 个字段,字段间由 FS 分隔
$0 完整的输入记录
ARGC 命令行参数的数目
ARGIND 命令行中当前文件的位置 (从 0 开始算)
ARGV 包含命令行参数的数组
CONVFMT 数字转换格式 (默认值为%.6g) ENVIRON 环境变量关联数组
ERRNO 最后一个系统错误的描述
FIELDWIDTHS 字段宽度列表 (用空格键分隔)
FILENAME 当前文件名
FNR 各文件分别计数的行号
FS 字段分隔符 (默认是任何空格)
IGNORECASE 如果为真,则进行忽略大小写的匹配
NF 一条记录的字段的数目
NR 已经读出的记录数,就是行号,从 1 开始
OFMT 数字的输出格式 (默认值是%.6g)
OFS 输出记录分隔符(输出换行符),输出时用指定的符号代替换行符
ORS 输出记录分隔符 (默认值是一个换行符)
RLENGTH 由 match 函数所匹配的字符串的长度
RS 记录分隔符 (默认是一个换行符)
RSTART 由 match 函数所匹配的字符串的第一个位置
SUBSEP 数组下标分隔符 (默认值是/034)
这种写法大家无需改变用'括起 awk 程序的习惯,是老外常用的写法.如:
var="test"
awk 'BEGIN{print "'$var'"}'
这种写法其实际是双括号变为单括号的常量,传递给了 awk.
如果 var 中含空格,为了 shell 不把空格作为分格符,便应该如下使用:
var="this is a test"
awk 'BEGIN{print "'"$var"'"}'
这种写法与上一种类似.如果变量含空格,则变为'""$var""'较为可靠.
例如:
var="this is a test"; export var;
awk 'BEGIN{print ENVIRON["var"]}'
例如:
var="this is a test"
awk -v awk_var="$var" 'BEGIN {print awk_var}'
这样便把系统变量 var 传递给了 awk 变量 awk_var.
“由 awk 向 shell 传递变量”,其思想无非是用 awk(sed/perl 等也是一样) 输出若干条 shell 命令,然后再用 shell 去执行这些命令。
eval $(awk 'BEGIN{print "var1='str1';var2='str2'"}')
或者
eval $(awk '{printf("var1=%s; var2=%s; var3=%s;",$1,$2,$3)}' abc.txt)
之后可以在当前 shell 中使用 var1,var2 等变量了。
echo "var1=$var1 ----- var2=$var2"
还有一种办法,使用 $() 来进行给 shell 变量赋值,如下:
val1=$(awk '{print $1}' abc.txt)
echo 4 7 | awk '{print $1*$2}'
28