awk使用总结

AWK是一款优秀的文本处理工具,Linux及类Unix环境中功能最强大的数据处理引擎之一。awk的衍生版本主要有nawk,gawk。linux系统下默认版本为gawk。

参数说明

短参数 长参数 说明
-F fs –field-separator=fs 指定输入文件折分隔符,fs是一个字符串或者是一个正则表达式,如-F:
-v var=val –assign=var=val 赋值一个用户定义变量
-f 脚本文件 –file=脚本文件 从脚本文件中读取awk命令
-m[fr] val 对val值设置内在限制,-mf选项限制分配给val的最大块数目;-mr选项限制记录的最大数目。这两个功能是Bell实验室版awk的扩展功能,在标准awk中不适用
-W compat –compat 在兼容模式下运行awk。所以gawk的行为和标准的awk完全一样,所有的awk扩展都被忽略
-W traditional –traditional
-W posix –posix 打开兼容模式。但有以下限制,不识别:/x、函数关键字、func、换码序列以及当fs是一个空格时,将新行作为一个域分隔符;操作符=不能代替^和^=;fflush无效
-W re-interval –re-interval 允许间隔正则表达式的使用,参考(grep中的Posix字符类),如括号表达式[[:alpha:]]
-W source=program-text –source=program-text 使用program-text作为源代码,可与-f命令混用
-W lint[=fatal] –lint[=fatal] 打印不能向传统unix平台移植的结构的警告
-W lint-old –lint-old 打印关于不能向传统unix平台移植的结构的警告
-W help –help 打印全部awk选项和每个选项的简短说明
-W usage –usage
-W copyright –copyright 打印简短的版权信息
-W copyleft –copyleft
-W copyright –copyright
-W version –version 打印bug报告信息的版本

内置变量

常见内置变量

变量 说明
$n 当前记录的第n个字段,字段间由FS分隔
$0 完整的输入记录
NF 一条记录的字段的数目
FS 字段分隔符(默认是任何空格)
OFS 输出记录分隔符(输出换行符),输出时用指定的符号代替换行符
RS 记录分隔符(默认是一个换行符)
ORS 输出记录分隔符(默认值是一个换行符)
NR 已经读出的记录数,就是行号,从1开始
FNR 各文件分别计数的行号

不常见内置变量

变量 说明
FILENAME 当前文件名
ARGC 命令行参数的数目
ARGV 包含命令行参数的数组
ARGIND 命令行中当前文件的位置(从0开始算)
FIELDWIDTHS 字段宽度列表(用空格键分隔)
IGNORECASE 如果为真,则进行忽略大小写的匹配
RLENGTH 由match函数所匹配的字符串的长度
RSTART 由match函数所匹配的字符串的第一个位置
CONVFMT 数字转换格式(默认值为%.6g)ENVIRON环境变量关联数组
OFMT 数字的输出格式(默认值是%.6g)
SUBSEP 数组下标分隔符(默认值是/034)
ERRNO 最后一个系统错误的描述

常用函数

函数 说明 使用范例
sub(regexp, replacement [, target]) 匹配记录中最大、最靠左边的子字符串的正则表达式,并用替换字符串替换这些字符串。
如果没有指定目标字符串就默认使用整个记录。替换只发生在第一次匹配时
awk ‘BEGIN { str = “water, water, everywhere”;sub(/at/, “ith”, str);print str}’
gsub(regexp, replacement [, target]) 整个文档中进行匹配 { gsub(/Britain/, “United Kingdom”); print }
index(in, find) 返回子字符串第一次被匹配的位置,偏移量从位置1开始 awk ‘BEGIN { print index(“peanut”, “an”) }’
substr(string, start [, length ]) 返回从位置1开始的子字符串,如果指定长度超过实际长度,就返回整个字符串 awk ‘BEGIN {string = “abcdef”;string = substr(string, 1, 2) “CDE” substr(string, 6);print string}’
split(string, array [, fieldsep [, seps ] ]) 可按给定的分隔符把字符串分割为一个数组。
如果分隔符没提供,则按当前FS值进行分割
split(“cul-de-sac”, a, “-“, seps)
length([string]) 返回记录的字符数 length(“abcde”)
match(string, regexp [, array]) 返回在字符串中正则表达式位置的索引,如果找不到指定的正则表达式则返回0 awk 'BEGIN {{if ($1 == "FIND") regex = $2; else { where = match($0, regex); if (where != 0) print "Match of", regex, "found at", where, "in", $0;}}}'
toupper和tolower 可用于字符串大小间的转换,该功能只在gawk中有效 toupper(“MiXeD cAsE 123”); tolower(“MiXeD cAsE 123”);
int(x) 取整,直接舍弃小数点后的数字 awk ‘BEGIN {print int(9999.99)}’
rand() 随机数,产生一个大于等于0而小于1的随机数 awk ‘BEGIN {print rand()}’

运算符

运算符 说明
<
<=
>
>=
!=
==
关系运算符
=
+=
-=
*=
/=
%=
^=
**=
赋值
&& 逻辑与
&#124;&#124; 逻辑或
+
-
!
一元加

逻辑非
! 匹配正则表达式和不匹配正则表达式
?: C条件表达式
空格 连接
$ 字段引用
in 数组成员
+
-

*
/
&


求余
++
增加
减少
作为前缀或后缀

awk正则

匹配符 说明
\w 匹配一个字母数字下划线任意组成的字符串
\W 匹配一个非字母数字下划线组成的字符串
\s 匹配任意空格类字符串,[[:space:]]的缩写
\S 匹配任意非空格类字符串,[^[:space:]]的缩写
\y 匹配一个单词开头或者末尾的空字符串。eg: '\yballs?\y' matches either ‘ball’ or ‘balls’, as a separate word.
\B 匹配单词内的空字符串,eg:/\Brat\B/ matches’crate’
< 匹配一个单词的开头的空字符串,锚定开始。eg: /\<away/ matches ‘away’ but not ‘stowaway’.
> 匹配一个单词的末尾的空字符串,锚定末尾。eg: /stow\>/ matches ‘stow’ but not ‘stowaway’.
` 匹配字符串起始的一个空字符串
' 匹配字符串末尾的一个空字符串

常用的format格式化输出

符号 说明
%s 显示字符串
%d, %i 十进制整数
%u 无符号整数
%f 显示浮点数
%g, %G 以科学计数法的格式或浮点数的格式显示数值
%e, %E 科学计数法显示数值
%c 显示字符的ASCII码
%% 显示%自身
修饰符:N 显示宽度
修饰符:- 左对齐
修饰符:+ 显示数值符号

应用范例

  • 格式化输出

    1
    2
    3
    4
    # echo 99 | awk 'BEGIN{ n=100 }{ printf("%s %s < "n"\n",$1,($1 < n ? "is" : "is not")) }'
    99 is < 100
    # echo 199 | awk 'BEGIN{ n=100 }{ printf("%s %s < "n"\n",$1,($1 < n ? "is" : "is not")) }'
    199 is not < 100
  • 使用正则,字符串匹配

    1
    2
    3
    # awk '$9 ~ /500/ {print $1,$7}' nginx_access_log
    # awk '$9 !~ /200/ {print $1,$7}' nginx_access_log
    # awk '!/200/ {print $1,$7}' nginx_access_log
  • if复合条件判断

    1
    2
    3
    {% raw %}
    cat nginx_access_log |awk '{if($9!="\"200\"" && $9 != "\"304\"" && $9 != "\"302\"" && $9 != "\"403\"") {print $9":"$11":"$7}}' |sort |uniq -c |sort -rn |head
    {% endraw %}
  • 使用数组进行分类汇总

    1
    2
    3
    4
    {% raw %}
    # netstat -ant | awk '/^tcp/ {state[$NF]++} END {for(s in state){if(state[s]>10)print s,state[s]}}'
    # tail -n 1000 nginx_access_log| awk '{stat[$9]++} END {for(c in stat){if(c !~ 200)print c,stat[c]}}'
    {% endraw %}
  • awk 去掉最后一列

    1
    awk -F / 'BEGIN{OFS="/"}{$NF=null;print $0}

参考