awk 简明教程

2022-06-27 12:31:12 浏览数 (1)

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)

%%

百分号(%)

0 人点赞