AWK 真是一个强大的工具,如果要想使好 shell,这是一个必须征服的工具,比如 python 来说的确有时候让你感到崩溃,但是其实都是相同的,一旦掌握,就是必不可少的杀器。

awk 语法

awk -F fs 'BEGIN{ } /pattern/ {action} END{ }' input-file ;-F 是指定分隔符
awk [选项参数] 'script' var=value file(s)awk [选项参数] -f scriptfile var=value file(s)

主要参数

运算符

= += -= = /= %= = *= 赋值
?: C 条件表达式
|| 逻辑或
&& 逻辑与
~ ~! 匹配正则表达式和不匹配正则表达式
< <= > >= != == 关系运算符
空格 连接

模式匹配

例子 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 中使用 shell 中的变量

一: "'$var'"

这种写法大家无需改变用'括起 awk 程序的习惯,是老外常用的写法.如:

var="test"
awk 'BEGIN{print "'$var'"}'

这种写法其实际是双括号变为单括号的常量,传递给了 awk.

如果 var 中含空格,为了 shell 不把空格作为分格符,便应该如下使用:

var="this is a test"
awk 'BEGIN{print "'"$var"'"}'

二: '"$var"'

这种写法与上一种类似.如果变量含空格,则变为'""$var""'较为可靠.

三: export 变量,使用 ENVIRON["var"] 形式,获取环境变量的值

例如:

var="this is a test"; export var;
awk 'BEGIN{print ENVIRON["var"]}'

四: 可以使用 awk 的-v 选项 (如果变量个数不多,个人偏向于这种写法)

例如:

var="this is a test"
awk -v awk_var="$var" 'BEGIN {print awk_var}'

这样便把系统变量 var 传递给了 awk 变量 awk_var.

awk 向 shell 变量传递值

“由 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)

awk 进行计算

echo 4 7 | awk '{print $1*$2}'
28


↙↙↙阅读原文可查看相关链接,并与作者交流