1. 概述
awk是一种编程语言,用于在linux/unix下对文本和数据进行处理。 数据可以来自标准输入、一个或多个文件,或其它命令的输出。 它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。 它在命令行中使用,但更多是作为脚本来使用。 awk 的处理文本和数据的方式是这样的,它逐行扫描文件,从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作如果没有指定处理动作,则把匹配的行显示到标准输出(屏幕),如果没有指定模式,则所有被操作所指定的行都被处理。 awk 分别代表其作者姓氏的第一个字母因为它的作者是三个人,分别是 Alfred Aho、Brian Kernighan、Peter Weinberger。 gawk是awk的GNU版本,它提供了 Bell 实验室和 GNU 的一些扩展。
2. awk 命令格式和选项
2.1. 调用命令
代码语言:javascript复制awk [options] 'script' var=value file(s)
或者。
代码语言:javascript复制awk [options] -f scriptfile var=value file(s)
可以运行 awk 命令或脚本。
2.2. 命令选项
awk 命令选项
选项 | 意义 |
---|---|
-F fs <b>or</b> —field-separator fs | 指定输入文件折分隔符,fs是一个字符串或者是一个正则表达式,如-F: |
-v var=value <b>or</b> —asign var=value | 赋值一个用户定义变量 |
—f scripfile <b>or</b> —file scriptfile | 从脚本文件中读取awk命令 |
-mf nnn | 限制分配给nnn的最大块数目,只能用于 gawk |
-mr nnn | 限制记录的最大数目,只能用于 gawk |
3. 模式和操作
awk 脚本是由若干个可选的模式和操作组成的:
代码语言:javascript复制awk pattern { action } ...
如: awk ’/root/‘ test,或 awk ’$3 < 100’ test。
模式和操作都是可选的,如果没有模式,则action应用到全部记录,如果没有action,则输出匹配全部记录默认情况下,每一个输入行都是一条记录,但用户可通过RS变量指定不同的分隔符进行分隔。
3.1. 模式
awk 命令的可选模式
模式 | 意义 |
---|---|
/正则表达式/ | 使用正则表达式过滤 |
关系表达式 | 可以用下面即将介绍的运算符表中的任意多个运算符组成 |
模式匹配表达式 | 用运算符~(匹配)和~!(不匹配) |
模式,模式 | 指定一个行的范围该语法不能包括BEGIN和END模式 |
BEGIN | 让用户指定在第一条输入记录被处理之前所发生的动作,通常可在这里设置全局变量 |
END | 让用户在最后一条输入记录被读取之后发生的动作 |
3.2. 操作
操作由一人或多个命令、函数、表达式组成,之间由换行符或分号隔开,并位于大括号内。 主要有四部份: 1. 变量或数组赋值 2. 输出命令 3. 内置函数 4. 控制流命令
如:
代码语言:javascript复制awk '$1 $2 < 100' test
如果第一和第二个域相加大于100,则打印这些行。
代码语言:javascript复制awk '$1 > 5 && $2 < 10' test
如果第一个域大于5,并且第二个域小于10,则打印这些行。
4. 环境变量
awk 中的环境变量
环境变量 | 意义 | |
---|---|---|
$n | 当前记录的第n个字段,字段间由FS分隔 | |
$0 | 完整的输入记录 | |
ARGC | 命令行参数的数目 | |
ARGIND | 命令行中当前文件的位置(从0开始算) | |
ARGV | 包含命令行参数的数组 | |
CONVFMT | 数字转换格式(默认值为%.6g) | |
ENVIRON | 环境变量关联数组 | |
ERRNO | 最后一个系统错误的描述 | |
FIELDWIDTHS | 字段宽度列表(用空格键分隔) | |
FILENAME | 当前文件名 | |
FNR | 同NR,但相对于当前文件 | |
FS | 字段分隔符(默认是任何空格) | |
IGNORECASE | 如果为真,则进行忽略大小写的匹配 | |
NF | 当前记录中的字段数 | |
NR | 当前记录数 | |
OFMT | 数字的输出格式(默认值是%.6g) | |
OFS | 输出字段分隔符(默认值是一个空格) | |
ORS | 输出记录分隔符(默认值是一个换行符) | |
RLENGTH | 由match函数所匹配的字符串的长度 | |
RS | 记录分隔符(默认是一个换行符) | |
RSTART | 由match函数所匹配的字符串的第一个位置 | |
SUBSEP | 数组下标分隔符(默认值是 34) |
5. 运算符
awk 运算符
运算符 | 意义 | ||
---|---|---|---|
= = -= = /= %= ^= *= | 赋值 | ||
? : | 条件表达式 | ||
&& | 逻辑或,逻辑与 | ||
~ ~! | 匹配正则表达式和不匹配正则表达式 | ||
< <= > >= != == | 关系运算符 | ||
- * / & | 加减乘除,取余 | ||
— | 自增,自减 | ||
^ | 求幂 | ||
$ | 字段引用 | ||
in | 数组成员判断 |
6. 变量
6.1. 外部传入变量
awk 可以在调用的时候使用 -v 参数指定外部赋值的变量:
代码语言:javascript复制awk '$1 {count = count $2 $3; print count}' test -v count=10
6.2. 内部变量
变量可以直接创建和赋值。 域变量也可被赋值和修改,如。
代码语言:javascript复制awk '{$2 = 100 $1; print }' test
7. BEGIN 和 END 模块
BEGIN模块后紧跟着动作块,这个动作块在awk处理任何输入文件之前执行,END不匹配任何的输入文件,但是执行动作块中的所有动作,它在整个输入文件处理完成后被执行。
8. 条件语句
代码语言:javascript复制{ if (expression) {
statement; statement; ...
}
else if (expression) {
statement; statement; ...
}
else if (expression) {
statement; statement; ...
}
else {
statement; statement; ...
}
}
9. 循环
awk 中有三种循环:while,for 和 special for。
9.1. while 循环
代码语言:javascript复制awk '{ i = 1; while ( i <= NF ) { print NF,$i; i }}' test
9.2. for 循环
代码语言:javascript复制awk '{for (i = 1; i<NF; i ) print NF,$i}' test
9.3. special for 循环
代码语言:javascript复制'{ for (item in arrayname) { print item,arrayname[item] } }'
9.4. next 语句
直接读取下一行,然后从头开始执行awk脚本。 类似于 C 语言中的 continue,但是 next 语句并非用于循环中。
代码语言:javascript复制{ if ($1 ~/test/) { next } else { print } }
10. 数组
10.1. 求数组长度
使用 length(arr) 可以求出数组长度。
代码语言:javascript复制awk 'BEGIN { info="it is a test"; lens=split(info,tA," "); print length(tA),lens; }'
10.2. 数组排序
使用 asort 可以对数组排序,返回数组长度。
代码语言:javascript复制awk 'BEGIN { info="it is a test"; split(info,tA," "); print asort(tA); }'
10.3. 输出数组内容
无序输出
有序输出
10.4. 判断键是否存在
if (key in array)
代码语言:javascript复制awk 'BEGIN { tB["a"]="a1"; tB["b"]="b1"; if( "c" in tB) { print "ok"; }; for(k in tB) { print k, tB[k]; } }'
10.5. 删除键值
delete array[key]
代码语言:javascript复制awk 'BEGIN{tB["a"]="a1";tB["b"]="b1";delete tB["a"];for(k in tB){print k,tB[k];}}'
11. 多维数组的使用
内建变量 SUBSEP 用来保存多维数组各维度间的分隔符,默认为“,”。
代码语言:javascript复制awk 'BEGIN {
for(i=1;i<=9;i )
{
for(j=1;j<=9;j )
{
tarr[i,j]=i*j;
}
}
for(m in tarr)
{
split(m,tarr2,SUBSEP);
print tarr2[1],"*",tarr2[2],"=",tarr[m];
}
}'
代码语言:javascript复制awk 'BEGIN{
for(i=1;i<=9;i )
{
for(j=1;j<=9;j )
{
tarr[i,j]=i*j;
print i,"*",j,"=",tarr[i,j];
}
}
}'
12. 内建函数
12.1. 算术函数
awk 的内建算数函数
函数 | 意义 |
---|---|
atan2( y, x ) | 返回 y/x 的反正切 |
cos( x ) | 返回 x 的余弦;x 是弧度 |
sin( x ) | 返回 x 的正弦;x 是弧度 |
exp( x ) | 返回 x 幂函数 |
log( x ) | 返回 x 的自然对数 |
sqrt( x ) | 返回 x 平方根 |
int( x ) | 返回 x 的截断至整数的值 |
rand( ) | 返回任意数字 n,其中 0 <= n < 1 |
srand( [Expr] ) | 将 rand 函数的种子值设置为 Expr 参数的值,或如果省略 Expr 参数则使用某天的时间返回先前的种子值 |
12.2. 字符串函数
awk 的内建字符串函数
函数 | 意义 |
---|---|
gsub( Ere, Repl, [ In ] ) | 除了正则表达式所有具体值被替代这点,它和 sub 函数完全一样地执行,。 |
sub( Ere, Repl, [ In ] ) | 用 Repl 参数指定的字符串替换 In 参数指定的字符串中的由 Ere 参数指定的扩展正则表达式的第一个具体值。sub 函数返回替换的数量。出现在 Repl 参数指定的字符串中的 &(和符号)由 In 参数指定的与 Ere 参数的指定的扩展正则表达式匹配的字符串替换。如果未指定 In 参数,缺省值是整个记录($0 记录变量)。 |
index( String1, String2 ) | 在由 String1 参数指定的字符串(其中有出现 String2 指定的参数)中,返回位置,从 1 开始编号。如果 String2 参数不在 String1 参数中出现,则返回 0(零)。 |
length [(String)] | 返回 String 参数指定的字符串的长度(字符形式)。如果未给出 String 参数,则返回整个记录的长度($0 记录变量)。 |
blength [(String)] | 返回 String 参数指定的字符串的长度(以字节为单位)。如果未给出 String 参数,则返回整个记录的长度($0 记录变量)。 |
substr( String, M, [ N ] ) | 返回具有 N 参数指定的字符数量子串。子串从 String 参数指定的字符串取得,其字符以 M 参数指定的位置开始。M 参数指定为将 String 参数中的第一个字符作为编号 1。如果未指定 N 参数,则子串的长度将是 M 参数指定的位置到 String 参数的末尾 的长度。 |
match( String, Ere ) | 在 String 参数指定的字符串(Ere 参数指定的扩展正则表达式出现在其中)中返回位置(字符形式),从 1 开始编号,或如果 Ere 参数不出现,则返回 0(零)。RSTART 特殊变量设置为返回值。RLENGTH 特殊变量设置为匹配的字符串的长度,或如果未找到任何匹配,则设置为 -1(负一)。 |
split( String, A, [Ere] ) | 将 String 参数指定的参数分割为数组元素 A[1], A[2], . . ., A[n],并返回 n 变量的值。此分隔可以通过 Ere 参数指定的扩展正则表达式进行,或用当前字段分隔符(FS 特殊变量)来进行(如果没有给出 Ere 参数)。除非上下文指明特定的元素还应具有一个数字值,否则 A 数组中的元素用字符串值来创建。 |
tolower( String ) | 返回 String 参数指定的字符串,字符串中每个大写字符将更改为小写。大写和小写的映射由当前语言环境的 LC_CTYPE 范畴定义。 |
toupper( String ) | 返回 String 参数指定的字符串,字符串中每个小写字符将更改为大写。大写和小写的映射由当前语言环境的 LC_CTYPE 范畴定义。 |
sprintf(Format, Expr, Expr, . . . ) | 根据 Format 参数指定的 printf 子例程格式字符串来格式化 Expr 参数指定的表达式并返回最后生成的字符串。 |
表中所有的 Ere 都可以是正则表达式。
12.3. 格式化输出 printf
awk printf 的参数格式
格式符 | 说明 |
---|---|
%d | 十进制有符号整数 |
%u | 十进制无符号整数 |
%f | 浮点数 |
%s | 字符串 |
%c | 单个字符 |
%p | 指针的值 |
%e | 指数形式的浮点数 |
%x | %X 无符号以十六进制表示的整数 |
%o | 无符号以八进制表示的整数 |
%g | 自动选择合适的表示法 |
12.4. 时间函数
awk 的时间函数
函数 | 意义 |
---|---|
mktime( YYYY MM DD HH MM SS[ DST]) | 生成时间格式 |
strftime([format [, timestamp]]) | 格式化时间输出,将时间戳转为时间字符串 具体格式,见下表. |
systime() | 得到时间戳,返回从1970年1月1日开始到当前时间(不计闰年)的整秒数 |
awk 日期格式符
格式符 | 意义 |
---|---|
%a | 星期几的缩写(Sun) |
%A | 星期几的完整写法(Sunday) |
%b | 月名的缩写(Oct) |
%B | 月名的完整写法(October) |
%c | 本地日期和时间 |
%d | 十进制日期 |
%D | 日期 08/20/99 |
%e | 日期,如果只有一位会补上一个空格 |
%H | 用十进制表示24小时格式的小时 |
%I | 用十进制表示12小时格式的小时 |
%j | 从1月1日起一年中的第几天 |
%m | 十进制表示的月份 |
%M | 十进制表示的分钟 |
%p | 12小时表示法(AM/PM) |
%S | 十进制表示的秒 |
%U | 十进制表示的一年中的第几个星期(星期天作为一个星期的开始) |
%w | 十进制表示的星期几(星期天是0) |
%W | 十进制表示的一年中的第几个星期(星期一作为一个星期的开始) |
%x | 重新设置本地日期(08/20/99) |
%X | 重新设置本地时间(12:00:00) |
%y | 两位数字表示的年(99) |
%Y | 当前月份 |
%Z | 时区(PDT) |
%% | 百分号(%) |