01. 简介

AWK是一个文本(面向行和列)处理工具,同时它也是一门脚本语言。
AWK其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母。后来AWK加入GUN后,更名为GAWK。
在Linux系统中,已经自动集成了GAWK,并兼容AWK。

02. 语法、选项

语法

gawk [ POSIX or GNU style options ] -f program-file [ -- ] file ...
gawk [ POSIX or GNU style options ] [ -- ] program-text file ...

选项

POSIX options:      GNU long options: (standard)
-f progfile         --file=progfile                   从程序文件中读取AWK程序,可以使用多个"-f"选项。
-F fs               --field-separator=fs              设置输入字段的分隔符(预定义变量FS的值)。
-v var=val          --assign=var=val                  在程序开始执行前,声明变量。这些变量=值可用于AWK
                                                      程序的BEGIN规则。

Short options:      GNU long options: (extensions)
-b                  --characters-as-bytes             将字符串视为单字节字符输入。
-c                  --traditional                     在兼容模式下运行。在兼容模式下,没有一个特定的GUN
                                                      的扩展被识别。
-C                  --copyright                       在标准输出上打印简短的GUN版权信息后并退出。
-d[file]            --dump-variables[=file]           打印全局变量、其类型和最终值的排序列表并转储到指
                                                      定文件。如果没有指定任何文件,则默认使用名为
                                                      awkvars的文件。
-D[file]            --debug[=file]                    启用对AWK程序的调试功能。默认情况下,调试器以交互
                                                      式从键盘读取命令(标准输入)。可选的"file"参数允
                                                      许指定一个带有命令列表的文件,调试器可以以非交互
                                                      式地执行这些命令。
-e 'program-text'   --source='program-text'           允许在命令行直接输入'AWK指令'作为AWK程序的源代
                                                      码。此选项允许与"-f"选项混合使用,它主要用于在
                                                      Shell脚本中使用中大型AWK程序。
-E file             --exec=file                       与"-f"选项相似,这应该与#!脚本一起使用,特别是对
                                                      于CGI应用程序,避免从命令行的URL上传入选项或源代
                                                      码(!)。这个选项将禁用命令行变量的指定。
-g                  --gen-pot                         扫描并解析AWK程序,并在标准输出上生成GUN.pot格式
                                                      的文件,其中包含程序中所有可本地化字符串的条目。
-h                  --help                            在标准输出上打印可用选项的简短帮助信息。
-i includefile      --include=includefile             加载AWK源库。这将使用AWKPATH环境变量来搜索库。
-l library          --load=library                    载入共享lib库。
-L[fatal|invalid]   --lint[=fatal|invalid]            提供有关可疑或不可移植到其他AWK实现构造的警告。
-M                  --bignum                          强制对数字进行任意精度的运算。如果GAWK为编译
                                                      GNU MPFR和MP库,则此选项无效。          
-N                  --use-lc-numeric                  识别输入数据中的八进制和十六进制值,请谨慎使用此
                                                      项!
-n                  --non-decimal-data                开启GAWK在解析输入数据时使用语言环境的小数点字
                                                      符。
-o[file]            --pretty-print[=file]             格式化输入的AWK程序,将漂亮格式版本的AWK程序输出
                                                      到指定文件。如果未指定文件则将输出到名
                                                      为"awkprof.out"的文件中在当前目录。
-O                  --optimize                        启用程序优化功能。对于常量的折叠和递归函数的尾部
                                                      调用消除。
-p[file]            --profile[=file]                  启用会话分析功能。并将分析数据写入到指定文件。
-P                  --posix                           打开兼容模式。但有以下限制:
                                                      - \x 无法识别转义序列;
                                                      - 当FS设置为单个空格时,只有空格和制表符Tab作为字
                                                        段分隔符,忽略换行符;
                                                      - 不允许在行的后面输入?和:;
                                                      - 无法识别关键字函数func;
                                                      - 运算符**和**=不能代替^和^=。
-r                  --re-interval                     使用正则表达式支持间隔表达式(比如{n,m}),默认情
                                                      况下它们是启用的。
-S                  --sandbox                         在沙盒中运行GAK,禁用system()函数,使用getline重
                                                      定向输入,使用print和printf重定向输出,并动态加载
                                                      扩展。
-t                  --lint-old                        提供有关不可移植到UNIX的AWK初始构造版本的警告。
-V                  --version                         在标准输出上打印GAWK的版本信息。

03. 执行AWK程序

AWK程序由一系列模式操作语句和可选函数定义组成。
AWK处理顺序:BEGIN{}–>{}–>END{}
BEGIN{} BEGIN规则块中的语句在开始处理文件中的文本之前执行一次。
END{} END规则块中的语句在文本处理完成之后执行一次

---
@include "filename"
@load "filename"
pattern   { action statements }
function name(parameter list) { statements }
---

GAWK首先从指定的程序文件中读取程序源,从–source选项读取,或者从命令行上的第一个非选项参数读取。-f和–source选项在命令行可以多次使用。
另外,可以使用以@include开头的行将其他源文件包含到程序中,从而使库的使用更容易。这相当于使用-i选项。
可以使用@load开头的行将共享库加载到程序中,这相当于使用-l选项。
当设置了AWKPATH环境变量时,使用-f和-i选项的时候只需要指定文件名称,则GAWK会自动从AWKPATH变量设置的目录下搜素到该文件。如果没有设置AWKPATH环境变量,则默认从”/usr/local/share/awk”目录下搜索。如果-f选项中包含”/”字符则执行路径搜索。
当设置了AWKLIBPATH环境变量时,这相当于使用-l选项。如果这个环境变量不存在,则使用默认路径”/usr/lib/lib/gawk”
GAWK执行AWK程序会按照以下顺序执行。首先,执行通过-v选项指定的所有变量赋值。接下来,GAWK会将程序编译成内部格式。然后,GAWK会执行BEGIN规则(如果有)中的代码,然后继续读取ARGV数组中命名的每个文件(直到ARGV[ARGC])。如果命令行上没有指定文件,则GAWK会从标准输入中读取。
如果命令行上文件名中具有”var=val”形式,则会将其视为变量赋值。变量var将被赋值为val,但是这将发生在任何BEGIN规则之后执行。
如果ARGV中的某个特定元素的值是空(“”)的,则GAWK会跳过它。
对于每个输入文件,如果存在一个BEGINFILE规则,在处理文件内容之前,GAWK会执行相关代码。在处理完文件后,GAWK会执行与ENDFILE关联的代码。
对于输入的每条记录,GAWK都会测试它是否匹配AWK程序中的任何模式。对于记录匹配的每个模式,GAWK执行相关的动作。
最后,在所有的输入都用完之后,GAWK将执行END规则(如果有)中的代码。

04. 变量、记录和字段

记录(Records)

一行表示一个记录。默认情况下记录由换行符分隔。
我们可以通过给RS内置变量重新赋值来修改分隔符,从而修改记录的分隔方式。分隔符允许是任意字符。另外RS允许是一个正则表达式,这将以能够被正则表达式匹配到的字符作为分隔符。然后,当在兼容模式下的时候,只使用字符串中的第一个字符来分隔记录。

字段(Fields)

一段字符串表示一个字段。默认情况下字段由空格分隔。
读取每个输入记录时,GAWK会使用FS内置变量作为字段的分隔符,将记录分割成多个字段。FS允许是任意字符或正则表达式。

变量和常量(Variables and Constant)

用特殊的非数字的字符来承载可变化的值,将其称之为变量。
量,测量东西的容器。用量来承载可变的值,在编程语言中将这个容器通常称之为变量,即可变化的量。不可变化的量称之为常量。

foo = 5      # 声明变量,创建变量并赋值
print foo    # 调用变量,打印变量的值

内置变量(Built-in Variables)

$n              可以使用$1~n来获取记录中分隔好的对应每个数值位置的字段。
$0              获取记录。
ARGC            命令行参数的数量(不包括选项和程序源)。
ARGIND          判断正在处理脚本文件的序号,如果只有一个脚本文件,则序号等于1。
ARGV            命令行参数组成的数组。可以使用数字索引取数组里面的值,比如ARGV[0]。
BINMODE         在非POSIX系统上,指定对文件的I/0使用"二进制"模式。
                有以下几个固定值:
                  1   输入文件
                  2   输出文件
                  3   所有文件
                  r   输入文件
                  w   输出文件
                  rw  所有文件
CONVFMT         将数字转换成字符类型时的格式,默认格式是"%.6g"。%表示格式化字符的意思,.
                .6表示小数点后面保留6位,g是格式化字符的标识,决定将浮点转换成科学计数法
                或者浮点型。例如:1.131425678,则当设置了CONVFMT="%.3f"后则输出的字符串
                为1.13。一般用"%f",这表示格式化字符串是一个浮点数。
ENVIRON         当前系统环境变量组成的数组。这是一个关联数组,可使用关联的键的名称获取对
                应键的值。例如:ENVIRON["HOME"]
ERRNO           当系统错误发生在获取行(getline)期间,当设置了ERRNO的值(这是一串关于错错
                误的描述信息),则会将该值打印出来。该值受非英语地区翻译的限制。
FIELDWIDTHS     使用指定宽度大小将一个字段(以空格分隔的)分隔成多个字段。例如:
                FIELDWIDTHS="1 2 1"则可以将abcd分割成a bc d。
FILENAME        当前输入文件的名称。如果命令行上没有指定任何文件,则该变量的值等于"-"。
FNR             当前输入文件的记录的编号,即行号。当存在多个文件时,每个文件的记录号都是
                从1开始的。
FPAT            记录中字段内容的正则表达式。当设置此变量时,字段与正则表达式匹配,而不是
                使用FS的值作为字段分隔符。
FS              输入字段分隔符,默认为空格。
FUNCTAB         一个数组,其索引和对应值是程序中所有用户定义的函数或扩展函数的名称。
IGNORECASE      控制对所有正则表达式操作字符串时是否区分大小写。如果IGNORECASE是一个非零
                值时,当执行正则表达式时,在规则中比较字符串和模式匹配时,使用FS和FPAT拆
                分字段时,使用RS分隔字段时,使用~和!~模糊匹配时,以及使用gensub()、
                gsub()、index()、match()、patsplit()、split()和sub()内置函数时都忽略大小
                写。但是,数组下标"索引或键"不受影响。但是asort()和asorti()函数会收到影
                响。
                默认情况下,IGNORECASE的初始值等于0,即区分大小写。
LINT            在AWK程序中提供对--lint选项的动态控制。如果为true,则GAWK打印警告。如果
                为false,则不会。当值等于"fatal"时,警告将变成致命错误。
NF              当前输入记录中的字段数量。
NR              当前输入文件记录的总数。
OFMT            数字的输出格式,默认是"%.6g"。
OFS             输出字段分隔符,默认是空格。
ORS             输出记录分隔符,默认是换行符。
PREC            任何精度浮点数的工作精度,默认为53。
PROCINFO        这是一个数组,该数组中的元素提供有关于正在运行的AWK程序的相关信息。
                PROCINFO["egid"]                     当前进程的EGID。
                PROCINFO["strftime"]                 AWK程序中使用的时间格式。
                PROCINFO["euid"]                     当前进程的EUID。
                PROCINFO["FS"]                       运行AWK程序所使用的字段分隔符对应的
                                                     内置变量"FS\FPAT\FIELDWIDTHS"。
                PROCINFO["identifiers"]              一个子数组,以AWK程序中使用的所有标
                                                     识符的名称为索引。元素的值是以下其
                                                     中一个:
                                                     "array"       标识符是数组。
                                                     "builtin"     标识符是内置函数。
                                                     "extension"   标识符是通过@load或-l
                                                                   加载的扩展功能。
                                                     "scalar"      标识符是标量。
                                                     "untyped"     标识符是无类型的。
                                                     "user"        标识符是用户自定义函
                                                                   数。

                PROCINFO["gid"]                      当前进程的GID。
                PROCINFO["pgrpid"]                   当前进程的进程组ID。
                PROCINFO["pid"]                      当前进程的ID。
                PROCINFO["ppid"]                     当前进程的父进程PID。
                PROCINFO["uid"]                      当前进程的UID。
                PROCINFO["sorted_in"]                如果此元素存在于PROCINFO中,则其值
                                                     控制在FOR循环中遍历数组元素的顺序。
                PROCINFO["input", "READ_TIMEOUT"]    从输入中读取数据的超时时间(毫秒)。
                                                     其中输入是重定向字符串或文件名,值
                                                     为0或小于0表示没有超时。
                PROCINFO["mpfr_version"]             MPFR库的版本。
                PROCINFO["gmp_version"]              MP库的版本。
                PROCINFO["prec_max"]                 MPFR库支持浮点数的最大精度。
                PROCINFO["prec_min"]                 MPFR库支持浮点数的最小精度。
                PROCINFO["api_major"]                扩展API的主要版本。
                PROCINFO["api_minor"]                扩展API的次要版本。
                PROCINFO["version"]                  GAWK的版本。


ROUNDMODE       舍入模式,用于数字的任意精度运算,默认为"N"(IEEE-754 roundTiesToEven 
                mode)。"N"或者"n"表示舍入为偶数,"U"或者"u"表示舍入为正数,"Z"或者"z"表
                示舍入为零。类似于四舍五入的一种模式。
RS              输入记录分隔符,默认是换行符。
RT              记录终止符,GAWK将RT设置为与RS指定的字符或正则表达式匹配的输入文本。
RSTART          match()匹配的第一个字符的索引。如果没有匹配则为0,这意味着字符索引是从1
                开始。
RLENGTH         match()匹配的字符串的长度。如果不匹配,则为-1。
SUBSEP          用于分隔数组元素中多个下标(索引或键)的字符,默认情况下为"\034",即","。
SYMTAB          一种数组,其索引是当前程序中所有定义的全局变量和数组的名称。该数组可用于
               间接访问,以读取或写入变量的值。
TEXTDOMAIN     AWK程序的文本域。用于查找程序字符串中的本地化翻译。

数组变量(Arrays)

由多个元素组成的集合,通常称之为数组。
AWK仅支持关联数组这种数据结构,索引可以是数字或字符串。
数组中的索引包括在”[]”中括号中,并使用SUBSEP内置变量的值作为元素分隔符,默认是”,”。

语法:array_name[index]=value
示例:
root@localhost:~# vim awk.script
BEGIN{
  x[i] = "A"  # 声明变量x是一个数组,在x中,它的第一个元素i="A",i是这个元素的键,"A"是值
  x[j] = "B"
  x[k] = "C"

  if (i in x) # 判断,如果i是x这个数组中的元素的话,则打印"hello world!"
    print "hello world!"
}
root@localhost:~# awk -f awk.script
hello, world

变量类型和转换(Variable Typing And Conversion)

变量和字段可以是数字或字符串。
被””包括的数字或字符串都将其视为是字符串,不被””包括的数字是数字。
如果想要强制将变量视为数字类型的化只需要赋值为0即可,比如:a=0;若要将其视为字符串的化,请将其与空字符串进行连接即可,比如:b=a””。
可以使用strtod(3)将字符串转换成数字。
可以使用CONVFMT的值作为sprintf(3)的格式化字符串,将数字转换成字符串。

示例:
root@localhost:~# vim awk.script
BEGIN{
  foo = 1.131425678
  CONVFMT="%.3f"      # 设置数字型转换成字符串型的格式
  foo = foo ""        # 将数字转换成字符串
  print foo           # 打印
}
root@localhost:~# awk -f awk.script 
1.131

字符串常量(String Constants)

AWK中的字符串常量是用双引号括起来的字符序列(如:”value”)。在字符串中可以识别某些转义序列,这些转义的字符具有特殊的作用。

\\     将反斜杠变成普通字符,它本身具有转义的作用。
\a     "alter"字符,通常是BEL的ASCLL编码的字符。
\b     退格。
\f     换页。
\n     换行,新行。
\r     回车。
\t     Tab。
\v     垂直标签。
\xhex  数字。由\x后面十六进制数字字符串所代表的字符。
\ddd   由1、2、3位八进制数字序列表示的字符。
\c     字面字符c。

05. 模式、动作

AWK是一种面向行的语言。首先是模式(Patterns),然后是动作(Actions)。动作的语句包含在{}中。在一个AWK程序中,可以没有模式或者没有动作,但两者不同同时都没有。如果缺少模式,则对输入的每条记录执行动作。缺少动作相当于打印整个记录,即{print}。

---
pattern{action}
---

注释信息以#号开始,一直到行结尾。
空行可用于分隔语句。
通常语句以换行符结束,然而,以逗号结尾的行{, ?, :, &&,或者||则并不是这样。
以do或者else结尾的行,其语句也会自动在后面的行继续。
在其他情况下,可以通过\结尾来继续行,在这种情况下,将忽略换行符。
多个语句可以通过;分隔放在一行上,这适用于分隔的两个语句都是对的情况下。以;分隔的后面的语句,它不会在乎前面的语句是否执行成功,它都会执行。

模式(Patterns)

AWK的模式可以是一下模式中其中一种:

特殊模式:
  BEGIN
  END
  BEGINFILE
  ENDFILE
正则模式:
  /regular expression/
关系模式:
  relational expression
多关系模式:
  pattern && pattern
  pattern || pattern
  pattern ? pattern : pattern
  ! pattern
范围模式:
  pattern1, pattern2
  (pattern)

BEGIN和END是两种特殊的模式,它们不需要对输入进行测试。BEGIN在任何输入被读取之前被执行,END在所有输入用尽时被执行。BEGIN和END模式不能在模式表达式中与其他模式结合使用。BEGIN和END将模式和动作合并使用BEGIN{}、END{},不能缺少动作部分。即在文件读取开始之前和之后执行。
BEGINFILE和ENDFILE是附加的特殊模式,其主体在读取每个命令行输入文件的第一条记录之前和读取每个文件的最后一条记录之后执行。即在文件记录的开始和结尾执行。
对于/regular expression/模式,将为与正则表达式匹配的每个输入记录执行关联语句。正则表达式与egrep中的正则表达式相同。
关系表达式可以使用下面有关操作的部分定义的任何运算符,它们通常用于测试某些字段是否匹配某些正则表达式。
&&、||、!是逻辑运算符等同于C语言中的AND、OR和NOT。
?:这个运算符与C语言中的相同。如果第一个模式(?前面的)满足为true,则就执行第二个模式(:前面),如果为false,则执行第三个模式(:后面)。
pattern1, pattern2通常称之为范围模式,限定一个范围,它匹配所有输入的记录,从pattern1匹配的记录开始,一直持续到pattern2匹配的记录结束。它不与任何其他类型的模式表达式相结合。

正则表达式(Regular Expressions)

正则表达式是egrep中发现的扩展类型。正则表达式由以下字符组成:

c               匹配非元字符c。
\c              匹配普通字符c。
.               匹配任意字符,包括换行符。
^               匹配字符串的开头。
$               匹配字符串的结尾。
[abc...]        一个字符列表,匹配abc...一系列中的任意字符。
[^abc...]       否定字符列表,匹配非abc...一系列外的任意字符。
r1|r2           轮换,匹配r1或者r2。
r1r2            连接,匹配r1,然后匹配r2。
r+              匹配一个或多个r。
r*              匹配0个或多个r。
r?              匹配0个或一个r。
(r)             分组匹配,()中的正则表达式是一个特殊字符组。
r{n}            区间表达式,n表示匹配r多少次。
r{n,}           区间表达式,n表示最少匹配r多少次。
r{n,m}          区间表达式,限定r的匹配次数。n表示最少匹配多少次,m表示最大匹配多少次。
\y              匹配空字符串,在单词的开头或结尾。
\B              匹配空字符串,在单词中。
\<              匹配空字符串,在单词的开头。
\>              匹配空字符串,在单词的结尾。
\s              匹配任意空字符。
\S              匹配任意非空字符。
\w              匹配任意由字母、数字或下划线组成的单词。
\W              匹配任意非字母、数字或下划线组成的字符。
\`              匹配空字符串,在缓冲区(字符串)的开头。
\'              匹配空字符串,在缓冲区(字符串)的结尾。

字符串常量在正则表达式中也是有效的。字符串常量有:

[:alnum:]       字母数字字符。
[:alpha:]       字母字符。
[:blank:]       空格或制表符。
[:cntrl:]       控制字符。
[:digit:]       数字字符。
[:graph:]       可打印又可见的字符。除了空格和制表符以外的所有字符。
[:lower:]       小写字母字符。
[:print:]       可打印字符,不是控制字符的字符,
[:punct:]       标点字符(不是字母、数字、控制字符或空格字符的字符)。
[:space:]       空格字符(包括空格、制表符)。
[:upper:]       大写字母字符。
[:xdigit:]      十六进制数字字符。

动作(Actions)

动作的语句包含在大括号{ var | Statements }中。动作语句包含大多数语言中常见的赋值语句、条件语句和循环语句。

操作符(Operators)

AWK的操作符,按优先级从高到低的操作顺序,有:

(...)                       分组。
$                           字段引用。
++ --                       递增或递减。前缀和后缀都有。
^                           求幂(平方),也可以使用**。
+ - !                       加、减、逻辑否。
* / %                       乘、除、求余。
+ -                         加、减。
space                       字符串连接。
|   |&                      为getline、print和printf提供管道I/O。
< > <= >= != ==             常规的关系运算符。
~ !~                        正则表达式匹配、否定匹配。
in                          数组成员身份。
&&                          逻辑与。
||                          逻辑或。
?:                          三元运算符,如果为true则指定:前面的语句,如果为false则执行:
                            后面的语句。常用于取代if语句。
= += -= *= /= %= ^=         赋值运算符。

控制语句(Control Statements)

if (condition) statement [ else statement ]
while (condition) statement
do statement while (condition)
for (expr1; expr2; expr3) statement
for (var in array) statement
break
continue
delete array[index]
delete array
exit [ expression ]
{ statements }
switch (expression) {
case value|regex : statement
...
[ default: statement ]
}

I/O语句(I/O Statements)

close(file [, how])             关闭文件、管道或协同进程。
getline                         设置$0,从下一个输入记录;设置NF,NR,FNR,RT。geline命令
                                执行成功时返回1,文件结束时返回0,错误时返回-1,出现错误
                                时,将描述问题的字符串设置为ERRNO并返回ERRNO的值。
getline <file                   设置$0,从文件的下一个记录;设置NF,RT。
getline var                     设置变量,从下一个输入记录;设置NR,FNR,RT。
getline var <file               设置变量,从文件的下一个记录;设置
command | getline [var]         运行命令,将命令执行的结果转化为$0或者变量,和RT。
command |& getline [var]        以协同进程的方式运行命令,将命令执行的结果转化为$0或者变
                                量,和RT。
next                            停止处理当前输入记录,读取下一个输入记录。
nextfile                        停止处理当前输入文件,读取下一个文件中的记录。
print                           打印当前记录,输入记录从ORS的值终止。
print expr-list                 打印表达式,每个表达式由OFS的值分隔,输出记录从ORS的值终
                                止。
print expr-list >file           打印表达式,从文件输入,每个表达式由OFS的值分隔,输出记
                                录从ORS的值终止。
printf fmt, expr-list           格式化打印。
printf fmt, expr-list >file     格式化打印,打印表达式从文件中读取。
system(cmd-line)                执行系统命令,执行完成后并返回退出状态。
fflush([file])                  刷新与打开的输出文件或管道文件所关联的所有缓冲区。如果文
                                件丢失或为空字符串,则刷新所有打开的输出文件和管道。
print ... >> file               将要打印的结果重定向追加到文件中。
print ... | command             将打印的结果交给管道后面的命令执行。
print ... |& command            以后台进程的方式将打印的结果交给管道后面的命令执行。

特殊文件名(Special File Names)

-                               标准输入。
/dev/stdin                      标准输入。
/dev/stdout                     标准输出。
/dev/stderr                     标准错误输出。
/dev/fd/n                       与打开文件描述符n关联的文件。
以下特殊的文件名可以与|&一起使用,可用于创建TCP/IP网络连接。
/inet/tcp/lport/rhost/rport     
/inet4/tcp/lport/rhost/rport
/inet6/tcp/lport/rhost/rport
/inet/udp/lport/rhost/rport
/inet4/udp/lport/rhost/rport
/inet6/udp/lport/rhost/rport

printf语句(printf Statement)

printf语句和sprintf()函数接受以下规范格式:

%c         字符。如果%c是数字,则它会被视为字符并打印出来,如果是字符串,它只打印第
           一个字符。
%d, %i     十进制整数。
%e, %E     格式为[-]d.dddddde[+-]dd的浮点数。
%f, %F     格式为[-]ddd.dddddd的浮点数。
%g, %G     使用%f或者%e转换,以较短者为准。
%o         无符号的八进制数(是一个整数)。
%u         无符号的十进制数(是一个整数)。
%s         字符串。
%x, %X     无符号的十六进制数(是一个整数)。%X使用ABCDEF,而不是abcdef。
%%         %字符。
可选的,可以在%和控制字母之间添加以下参数:
count$     在格式化的时候使用count的参数。
-          使字段左对齐。
space      对于数字转换,正值前缀为空格,负值前缀为减号。
+          在宽度修饰符之前使用,为数字转换提供一个符号,使格式化的字符是一个正数。
#          对于某些控制字母使用"替换格式",对于%o,提供一个前导零。对于%x或%X提供前导0x
           或0X以得出非零结果。
0          前导0充当一个标志,指示输出应填充0,而不是空格。这只适用于数字输出格式。
'          单引号表示在十进制数值中插入千位分隔符。
width      设置字段的宽度。
.prec      设置打印时要使用的精度的数字。对于%e、%E、%f、%F格式小数点右侧的位数。

数值函数(Numeric Functions)

atan2(y, x)        返回y/x的反正切。
cos(expr)          返回expr的余弦,也就是弧度。
exp(expr)          返回expr幂函数。
int(expr)          返回expr的整数部分。
log(expr)          返回expr的自然对数。
rand()             返回一个0到1之间的随机数N。0<=N<1。
sin(expr)          返回expr的正弦,以弧度为单位。
sqrt(expr)         返回expr的平方根。
srand([expr])      如果将expr设置为rand()函数的话,则返回rand()的种子值0或者1,如果啥都
                   不设置的话,则srand()会输出当前以秒为单位的时间戳。

字符串函数(String Functions)

asort(s [, d [, how] ])           对数组s的值进行排序,并将排序后的值写入到新的数据d
                                  中,新数组的索引是1开始的。一般需要结合for语句使用。
                                  示例:
                                        root@localhost:~# vim awk.script 
                                        BEGIN{
                                          a[1] = "C"
                                          a[2] = "B"
                                          a[3] = "F"
                                          a[4] = "G"
                                          for (i=1;i<=asort(a,b);i++)
                                            print b[i]
                                        }
                                        root@localhost:~# awk -f awk.script 
                                        B
                                        C
                                        F
                                        G
asorti(s [, d [, how] ])          对数组s的键进行排序,并将排序后的键写入到目标数组d中。
                                  示例:
                                        root@localhost:~# vim awk.script
                                        BEGIN{
                                          a[4] = "C"
                                          a[3] = "B"
                                          a[9] = "F"
                                          a[1] = "G"
                                          for (i=1;i<=asorti(a,b);i++)
                                            print(b[i], a[b[i]])
                                        }
                                        root@localhost:~# awk -f awk.script 
                                        1 G
                                        3 B
                                        4 C
                                        9 F
gensub(r, s, h [, t])             替换字符串。在目标字符串t中搜索正则表达式r的匹配项。h
                                  是要替换的字符位置,如果h是以g或G开头的字符串,则将r的                   
                                  所有匹配项替换为s。t是可选的,如果没有t则默认从输入记
                                  录中读取。
                                  示例:
                                        root@localhost:~# vim awk.script
                                        BEGIN{
                                          string = "111111"
                                          print gensub("1","x","4",string)
                                        }
                                        root@localhost:~# awk -f awk.script 
                                        111x11
gsub(r, s [, t])                  替换字符串。在目标字符串t中搜索正则表达式r的匹配项,将
                                  其替换为s,并返回替换次数。直接打印gsub()返回的是替换
                                  数,如果想要打印被替换的字符串,则请将gsub()执行的下一
                                  行打印字符串即可。
                                  示例:
                                        root@localhost:~# vim awk.script
                                        BEGIN{
                                          string = "111111"
                                          gsub("1","x",string)
                                          print string
                                        }
                                        root@localhost:~# awk -f awk.script 
                                        xxxxxx
index(s, t)                       返回字符串t在字符串s中的索引位置,不存在的话返回0。
                                  示例:
                                        root@localhost:~# vim awk.script
                                        BEGIN{
                                          print index("hello world!", "l")
                                        }
                                        root@localhost:~# awk -f awk.script 
                                        3
length([s])                       返回字符串的长度。
                                  示例:
                                        root@localhost:~# vim awk.script
                                        BEGIN{
                                          string = "hello world!"
                                          print length(string)
                                        }
                                        root@localhost:~# awk -f awk.script 
                                        12
match(s, r [, a])                 返回正则表达式r在字符串s的位置,如果r不存在则返回0,并
                                  设置为RSTART和RLENGTH的值。如果存在数组a,则会将正则表
                                  达式中以()的匹配字符进行分组并将其转换成数组a的元素。
                                  示例:
                                        root@localhost:~# vim awk.script
                                        BEGIN{
                                          string = "hello world!"
                                          print match(string,"(.*)(w\\S*!$)",a)
                                          print a[1]
                                        }
                                        root@localhost:~# awk -f awk.script 
                                        1
                                        hello
patsplit(s, a [, r [, seps] ])    拆分字符串。将字符串s拆分到数组a中,并返回数组a中的元
                                  素的个数,可以使用正则表达式r匹配字段进行拆分,否则使
                                  用空格分隔符进行拆分,可以设置seps分隔字段,则会返回匹
                                  配该字段的数量。
                                  示例:
                                        root@localhost:~# vim awk.script
                                        BEGIN{
                                          string = "hello world hello world"
                                          print patsplit(string,a,"\\S*")  # 返回拆分后字段的数量
                                          print a[2]                       # 取指定索引的字段
                                        }
                                        root@localhost:~# awk -f awk.script 
                                        4
                                        world
split(s, a [, r [, seps] ])       拆分字符串。将字符串s拆分到数组a中,并返回数组a中的元
                                  素的个数。可以设置分隔符seps或者正则表达式r。
                                  示例:
                                        root@localhost:~# vim awk.script
                                        BEGIN{
                                          string = "hello world hello world"
                                          print split(string,a," ")    # 返回拆分后字段的数量
                                          print a[2]                   # 取指定索引的字段
                                        }
                                        root@localhost:~# awk -f awk.script 
                                        4
                                        world
sprintf(fmt, expr-list)           格式化字符串输出。根据格式化字符填充对应的字段,然后返
                                  回被新格式的字符串。
strtonum(str)                     检查字符串str,并返回它的数值。如果字符串str是以前导0
                                  开始则将其视为八进制数,如果是以0x开头则将其视为十六进
                                  制数,否则它是一个十进制的数值。
sub(r, s [, t])                   与gsub()类似,但仅替换第一个匹配到字符串。
                                  示例:
                                        root@localhost:~# vim awk.script
                                        BEGIN{
                                          string = "11111-@11111-@3333"
                                          sub("[0-9]+","heihei",string)
                                          print string
                                        }
                                        root@localhost:~# awk -f awk.script 
                                        heihei-@11111-@3333
substr(s, i [, n])                截取字符串。返回在字符串s中从位置i开始到位置n结束的字
                                  符串。
                                  示例:
                                        root@localhost:~# vim awk.script 
                                        BEGIN{
                                          string = "11111-@22222-@3333"
                                          print substr(string,7,6)
                                        }
                                        root@localhost:~# awk -f awk.script 
                                        @22222
tolower(str)                      大小写转换。将字符串str中的大写字符转换成小写字符后输
                                  出。
toupper(str)                      大小写转换。将字符串str中的小写字符转换成大写字符后输
                                  出。

时间函数(Time Functions)

由于AWK程序的主要用途之一是处理包含时间戳信息的日志文件,GAWK提供以下获取时间戳和格式化的功能函数。

mktime(datespec)                  将datespec转换成与systime()相同格式的时间戳。datespec
                                  是格式为YYYY MM DD HH MM SS DST 的字符串。这将返回以秒
                                  为单位的时间戳。
                                  示例:
                                        root@localhost:~# vim awk.script
                                        BEGIN{
                                          print mktime("2021 01 25 18 48 00")
                                        }
                                        root@localhost:~# awk -f awk.script 
                                        1611571680                             
strftime([format [, timestamp[, utc-flag]]])
                                  根据指定的时间格式,返回对应的时间。如果指定了时间戳
                                  timestamp,则返回对应时间戳的时间。如果设置UTC标志utc-
                                  flag的值为非0时,则输出的时间格式时UTC。
                                  示例:
                                        root@localhost:~# vim awk.script
                                        BEGIN{
                                          print strftime("%Y-%m-%d %H:%M:%S",1611571885)
                                        }
                                        root@localhost:~# awk -f awk.script 
                                        2021-01-25 18:51:25
systime()                         返回当前系统的时间戳,以秒为单位。

位操作函数(Bit Manipulations Functions)

and(v1, v2 [, ...])
compl(val)
lshift(val, count)
or(v1, v2 [, ...])
rshift(val, count)
xor(v1, v2 [, ...])

类型函数(Type Function)

isarray(x)     如果x是一个数组,则返回true,否则返回false。

国际化函数(Internationalization Functions)

bindtextdomain(directory [, domain])
dcgettext(string [, domain [, category]])
dcngettext(string1, string2, number [, domain [, category]])

用户自定义函数(User-Defined Functions)

用户可以根据自己的需求自定义函数,并在其他地方应用。在函数中可以使用return语句返回执行后的结果。

语法:function name(parameter list) { statements }
示例:
root@localhost:~# vim awk.script
# 这是一个自定义的加法函数
function addition(a, b)               # 创建函数
{
  result = a + b
  return result                       # 返回结果
}

BEGIN{
  print addition(1,2)                 # 引用函数
}
root@localhost:~# awk -f awk.script 
3

退出状态(Exit Status)

可以使用exit语句设置AWK程序的退出状态。
如果程序执行没有问题,GAWK通常使用常量EXIT_SUCCESS的值退出,这通常是0。
如果发生错误,GAWK会使用常量EXIT_FAILURE的值退出,这通常是1。
如果由于致命错误而退出,则退出状态为2。

06. 常用示例

查看最近登录用户

[root@localhost ~]# last -n 5 | awk '{print $1}'
root
root
root
reboot
root

查看系统中有哪些用户

[root@localhost ~]# cat /etc/passwd | awk -F ":" '{print $1}'	
root
bin
daemon
adm
lp
sync

查看系统有哪些用户,以及查看是否允许用户系统登录

[root@localhost ~]# cat /etc/passwd | awk -F ":" '{print $1"\t"$7}'
root	/bin/bash
bin	/sbin/nologin
daemon	/sbin/nologin
adm	/sbin/nologin
lp	/sbin/nologin
sync	/bin/sync

查看内存空闲值大小是否超过500M,如果是则打印出来

[root@localhost ~]# free -m |head -n 2 |grep -n 2|awk '{if($4>500){print $4}}'
593

获取CPU使用率TOP10的进程,并限制每行进程的字符长度

[root@localhost ~]# ps aux --sort=-%cpu|head -n 10 |awk '{print substr($0,0,120)}')

显示空间使用率大于80%的硬盘

[root@localhost ~]# df -Th |grep -v '^Filesystem'|awk '{split($6,a,"%");if(a[1]>80){print $0}}'

版权声明:本文为network-ren原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/network-ren/p/14329197.html