AWK - 快速指南
AWK - 概述
AWK 是一种解释型编程语言。它非常强大,专门为文本处理而设计。它的名字源自其作者的姓氏——阿尔弗雷德·阿霍 (Alfred Aho)、彼得·温伯格 (Peter Weinberger) 和布莱恩·科尼汉 (Brian Kernighan)。
GNU/Linux 发行的 AWK 版本由自由软件基金会 (FSF) 编写和维护;它通常被称为GNU AWK。
AWK 的类型
以下是 AWK 的变体 -
AWK - 来自 AT & T 实验室的原始 AWK。
NAWK - AT&T 实验室 AWK 的更新和改进版本。
GAWK - 它是 GNU AWK。所有 GNU/Linux 发行版都附带 GAWK。它与 AWK 和 NAWK 完全兼容。
AWK 的典型用途
使用 AWK 可以完成无数任务。下面列出的只是其中的一些 -
- 文本处理,
- 生成格式化的文本报告,
- 执行算术运算,
- 执行字符串操作等等。
AWK - 环境
本章介绍如何在 GNU/Linux 系统上设置 AWK 环境。
使用包管理器安装
一般来说,AWK 在大多数 GNU/Linux 发行版上默认可用。您可以使用which命令来检查它是否存在于您的系统上。如果您没有 AWK,请使用 Advance Package Tool (APT)包管理器将其安装在基于 Debian 的 GNU/Linux 上,如下所示 -
[jeryy]$ sudo apt-get update [jeryy]$ sudo apt-get install gawk
同样,要在基于 RPM 的 GNU/Linux 上安装 AWK,请使用 Yellowdog Updator Modifier yum包管理器,如下所示 -
[root]# yum install gawk
安装后,确保可以通过命令行访问 AWK。
[jerry]$ which awk
执行上面的代码,你会得到以下结果 -
/usr/bin/awk
从源代码安装
由于 GNU AWK 是 GNU 项目的一部分,因此其源代码可以免费下载。我们已经了解了如何使用包管理器安装 AWK。现在让我们了解如何从源代码安装 AWK。
以下安装适用于任何 GNU/Linux 软件,以及大多数其他免费程序。以下是安装步骤 -
步骤 1 - 从真实的地方下载源代码。命令行实用程序wget可以用于此目的。
[jerry]$ wget http://ftp.gnu.org/gnu/gawk/gawk-4.1.1.tar.xz
步骤 2 - 解压缩并提取下载的源代码。
[jerry]$ tar xvf gawk-4.1.1.tar.xz
步骤 3 - 切换到目录并运行配置。
[jerry]$ ./configure
步骤 4 - 成功完成后,配置会生成 Makefile。要编译源代码,请发出make命令。
[jerry]$ make
步骤 5 - 您可以运行测试套件以确保构建是干净的。这是一个可选步骤。
[jerry]$ make check
步骤 6 - 最后,安装 AWK。确保您拥有超级用户权限。
[jerry]$ sudo make install
这就对了!您已成功编译并安装 AWK。通过执行awk命令来验证它,如下所示 -
[jerry]$ which awk
执行此代码时,您将得到以下结果 -
/usr/bin/awk
AWK-工作流程
要成为 AWK 程序员专家,您需要了解其内部结构。AWK 遵循简单的工作流程 - 读取、执行和重复。下图描述了 AWK 的工作流程 -
读
AWK 从输入流(文件、管道或标准输入)读取一行并将其存储在内存中。
执行
所有 AWK 命令都按顺序应用于输入。默认情况下,AWK 在每一行执行命令。我们可以通过提供模式来限制这一点。
重复
重复此过程直到文件到达末尾。
程序结构
现在让我们了解一下AWK的程序结构。
开始块
BEGIN 块的语法如下 -
句法
BEGIN {awk-commands}
BEGIN 块在程序启动时执行。它只执行一次。这是初始化变量的好地方。BEGIN 是 AWK 关键字,因此它必须为大写。请注意,此块是可选的。
身体块
主体块的语法如下 -
句法
/pattern/ {awk-commands}
主体块在每个输入行上应用 AWK 命令。默认情况下,AWK 在每一行上执行命令。我们可以通过提供模式来限制这一点。请注意,Body 块没有关键字。
结束块
END 块的语法如下 -
句法
END {awk-commands}
END 块在程序结束时执行。END 是 AWK 关键字,因此它必须为大写。请注意,此块是可选的。
让我们创建一个文件marks.txt,其中包含序列号、学生姓名、科目名称和获得的分数。
1) Amit Physics 80 2) Rahul Maths 90 3) Shyam Biology 87 4) Kedar English 85 5) Hari History 89
现在让我们使用 AWK 脚本显示带有标题的文件内容。
例子
[jerry]$ awk 'BEGIN{printf "Sr No\tName\tSub\tMarks\n"} {print}' marks.txt
执行此代码时,会产生以下结果 -
输出
Sr No Name Sub Marks 1) Amit Physics 80 2) Rahul Maths 90 3) Shyam Biology 87 4) Kedar English 85 5) Hari History 89
首先,AWK 打印 BEGIN 块中的标头。然后在主体块中,它从文件中读取一行并执行 AWK 的打印命令,该命令仅在标准输出流上打印内容。重复此过程直到文件到达末尾。
AWK - 基本语法
AWK 使用起来很简单。我们可以直接从命令行提供 AWK 命令,也可以以包含 AWK 命令的文本文件的形式提供 AWK 命令。
AWK 命令行
我们可以在命令行的单引号内指定 AWK 命令,如下所示 -
awk [options] file ...
例子
考虑一个包含以下内容的文本文件marks.txt -
1) Amit Physics 80 2) Rahul Maths 90 3) Shyam Biology 87 4) Kedar English 85 5) Hari History 89
让我们使用 AWK 显示文件的完整内容,如下所示 -
例子
[jerry]$ awk '{print}' marks.txt
执行此代码时,您将得到以下结果 -
输出
1) Amit Physics 80 2) Rahul Maths 90 3) Shyam Biology 87 4) Kedar English 85 5) Hari History 89
AWK 程序文件
我们可以在脚本文件中提供 AWK 命令,如下所示 -
awk [options] -f file ....
首先,创建一个包含 AWK 命令的文本文件command.awk,如下所示 -
{print}
现在我们可以指示 AWK 从文本文件中读取命令并执行操作。在这里,我们获得了与上例所示相同的结果。
例子
[jerry]$ awk -f command.awk marks.txt
执行此代码时,您将得到以下结果 -
输出
1) Amit Physics 80 2) Rahul Maths 90 3) Shyam Biology 87 4) Kedar English 85 5) Hari History 89
AWK 标准选项
AWK 支持以下可以从命令行提供的标准选项。
-v 选项
该选项为变量赋值。它允许在程序执行之前进行赋值。以下示例描述了 -v 选项的用法。
例子
[jerry]$ awk -v name=Jerry 'BEGIN{printf "Name = %s\n", name}'
执行此代码时,您将得到以下结果 -
输出
Name = Jerry
--dump-variables[=文件] 选项
它打印全局变量的排序列表及其最终值到文件。默认文件是awkvars.out。
例子
[jerry]$ awk --dump-variables '' [jerry]$ cat awkvars.out
执行上面的代码,你会得到以下结果 -
输出
ARGC: 1 ARGIND: 0 ARGV: array, 1 elements BINMODE: 0 CONVFMT: "%.6g" ERRNO: "" FIELDWIDTHS: "" FILENAME: "" FNR: 0 FPAT: "[^[:space:]]+" FS: " " IGNORECASE: 0 LINT: 0 NF: 0 NR: 0 OFMT: "%.6g" OFS: " " ORS: "\n" RLENGTH: 0 RS: "\n" RSTART: 0 RT: "" SUBSEP: "\034" TEXTDOMAIN: "messages"
--help 选项
此选项在标准输出上打印帮助消息。
例子
[jerry]$ awk --help
执行此代码时,您将得到以下结果 -
输出
Usage: awk [POSIX or GNU style options] -f progfile [--] file ... Usage: awk [POSIX or GNU style options] [--] 'program' file ... POSIX options : GNU long options: (standard) -f progfile --file=progfile -F fs --field-separator=fs -v var=val --assign=var=val Short options : GNU long options: (extensions) -b --characters-as-bytes -c --traditional -C --copyright -d[file] --dump-variables[=file] -e 'program-text' --source='program-text' -E file --exec=file -g --gen-pot -h --help -L [fatal] --lint[=fatal] -n --non-decimal-data -N --use-lc-numeric -O --optimize -p[file] --profile[=file] -P --posix -r --re-interval -S --sandbox -t --lint-old -V --version
--lint[=致命] 选项
此选项可以检查不可移植或可疑的结构。当提供参数fatal时,它将警告消息视为错误。以下示例演示了这一点 -
例子
[jerry]$ awk --lint '' /bin/ls
执行此代码时,您将得到以下结果 -
输出
awk: cmd. line:1: warning: empty program text on command line awk: cmd. line:1: warning: source file does not end in newline awk: warning: no program text at all!
--posix 选项
此选项打开严格的 POSIX 兼容性,其中所有常见的和特定于 gawk 的扩展都被禁用。
--profile[=文件] 选项
此选项会在文件中生成程序的精美打印版本。默认文件是awkprof.out。下面的简单例子说明了这一点 -
例子
[jerry]$ awk --profile 'BEGIN{printf"---|Header|--\n"} {print} END{printf"---|Footer|---\n"}' marks.txt > /dev/null [jerry]$ cat awkprof.out
执行此代码时,您将得到以下结果 -
输出
# gawk profile, created Sun Oct 26 19:50:48 2014 # BEGIN block(s) BEGIN { printf "---|Header|--\n" } # Rule(s) { print $0 } # END block(s) END { printf "---|Footer|---\n" }
--traditional 选项
此选项禁用所有特定于 gawk 的扩展。
--version 选项
该选项显示 AWK 程序的版本信息。
例子
[jerry]$ awk --version
执行此代码时,会产生以下结果 -
输出
GNU Awk 4.0.1 Copyright (C) 1989, 1991-2012 Free Software Foundation.
AWK - 基本示例
本章介绍了几个有用的 AWK 命令及其相应的示例。考虑使用以下内容处理文本文件marks.txt -
1) Amit Physics 80 2) Rahul Maths 90 3) Shyam Biology 87 4) Kedar English 85 5) Hari History 89
打印列或字段
您可以指示 AWK 仅打印输入字段中的某些列。以下示例演示了这一点 -
例子
[jerry]$ awk '{print $3 "\t" $4}' marks.txt
执行此代码时,您将得到以下结果 -
输出
Physics 80 Maths 90 Biology 87 English 85 History 89
在文件marks.txt中,第三列包含主题名称,第四列包含在特定主题中获得的分数。让我们使用 AWK 打印命令打印这两列。在上面的示例中,$3 和 $4分别表示输入记录中的第三个和第四个字段。
打印所有行
默认情况下,AWK 打印所有与模式匹配的行。
例子
[jerry]$ awk '/a/ {print $0}' marks.txt
执行此代码时,您将得到以下结果 -
输出
2) Rahul Maths 90 3) Shyam Biology 87 4) Kedar English 85 5) Hari History 89
在上面的示例中,我们正在搜索表单模式a。当模式匹配成功时,它会执行主体块中的命令。在没有正文块的情况下 - 采取默认操作,即打印记录。因此,以下命令会产生相同的结果 -
例子
[jerry]$ awk '/a/' marks.txt
按模式打印列
当模式匹配成功时,AWK 默认打印整个记录。但您可以指示 AWK 仅打印某些字段。例如,以下示例在模式匹配成功时打印第三个和第四个字段。
例子
[jerry]$ awk '/a/ {print $3 "\t" $4}' marks.txt
执行此代码时,您将得到以下结果 -
输出
Maths 90 Biology 87 English 85 History 89
以任意顺序打印列
您可以按任何顺序打印列。例如,以下示例打印第四列,然后打印第三列。
例子
[jerry]$ awk '/a/ {print $4 "\t" $3}' marks.txt
执行上面的代码,你会得到以下结果 -
输出
90 Maths 87 Biology 85 English 89 History
计数并打印匹配的图案
让我们看一个示例,您可以在其中计算并打印模式匹配成功的行数。
例子
[jerry]$ awk '/a/{++cnt} END {print "Count = ", cnt}' marks.txt
执行此代码时,您将得到以下结果 -
输出
Count = 4
在此示例中,当模式匹配成功时,我们增加计数器的值,并在 END 块中打印该值。请注意,与其他编程语言不同,在使用变量之前无需声明变量。
打印超过 18 个字符的行
让我们只打印那些包含超过 18 个字符的行。
例子
[jerry]$ awk 'length($0) > 18' marks.txt
执行此代码时,您将得到以下结果 -
输出
3) Shyam Biology 87 4) Kedar English 85
AWK 提供了一个内置的长度 函数,用于返回字符串的长度。$0变量存储整行,并且在没有主体块的情况下,将采取默认操作,即打印操作。因此,如果一行超过 18 个字符,则比较结果为 true,并且该行将被打印。
AWK - 内置变量
AWK 提供了几个内置变量。它们在编写 AWK 脚本时发挥着重要作用。本章演示了内置变量的用法。
标准 AWK 变量
标准 AWK 变量将在下面讨论。
ARGC
它意味着命令行中提供的参数数量。
例子
[jerry]$ awk 'BEGIN {print "Arguments =", ARGC}' One Two Three Four
执行此代码时,您将得到以下结果 -
输出
Arguments = 5
但是为什么当你只传递 4 个参数时 AWK 显示 5 呢?只需查看以下示例即可消除您的疑虑。
ARGV
它是一个存储命令行参数的数组。该数组的有效索引范围为 0 到 ARGC-1。
例子
[jerry]$ awk 'BEGIN { for (i = 0; i < ARGC - 1; ++i) { printf "ARGV[%d] = %s\n", i, ARGV[i] } }' one two three four
执行此代码时,您将得到以下结果 -
输出
ARGV[0] = awk ARGV[1] = one ARGV[2] = two ARGV[3] = three
卷积FMT
它代表数字的转换格式。它的默认值为%.6g。
例子
[jerry]$ awk 'BEGIN { print "Conversion Format =", CONVFMT }'
执行此代码时,您将得到以下结果 -
输出
Conversion Format = %.6g
环境
它是环境变量的关联数组。
例子
[jerry]$ awk 'BEGIN { print ENVIRON["USER"] }'
执行此代码时,您将得到以下结果 -
输出
jerry
要查找其他环境变量的名称,请使用env命令。
文件名
它代表当前文件名。
例子
[jerry]$ awk 'END {print FILENAME}' marks.txt
执行此代码时,您将得到以下结果 -
输出
marks.txt
请注意,BEGIN 块中未定义 FILENAME。
FS
它表示(输入)字段分隔符,其默认值为空格。您还可以使用-F命令行选项来更改此设置。
例子
[jerry]$ awk 'BEGIN {print "FS = " FS}' | cat -vte
执行此代码时,您将得到以下结果 -
输出
FS = $
核因子
它表示当前记录中的字段数。例如,以下示例仅打印包含两个以上字段的行。
例子
[jerry]$ echo -e "One Two\nOne Two Three\nOne Two Three Four" | awk 'NF > 2'
执行此代码时,您将得到以下结果 -
输出
One Two Three One Two Three Four
NR
它代表当前记录的数量。例如,如果当前记录数小于 3,以下示例将打印该记录。
例子
[jerry]$ echo -e "One Two\nOne Two Three\nOne Two Three Four" | awk 'NR < 3'
执行此代码时,您将得到以下结果 -
输出
One Two One Two Three
FNR
它与NR类似,但相对于当前文件。当 AWK 操作多个文件时它很有用。FNR 的值随新文件重置。
正交频域调制
它表示输出格式编号,默认值为%.6g。
例子
[jerry]$ awk 'BEGIN {print "OFMT = " OFMT}'
执行此代码时,您将得到以下结果 -
输出
OFMT = %.6g
欧福斯
它表示输出字段分隔符,默认值为空格。
例子
[jerry]$ awk 'BEGIN {print "OFS = " OFS}' | cat -vte
执行此代码时,您将得到以下结果 -
输出
OFS = $
口服补液盐
表示输出记录分隔符,默认值为换行符。
例子
[jerry]$ awk 'BEGIN {print "ORS = " ORS}' | cat -vte
执行上面的代码,你会得到以下结果 -
输出
ORS = $ $
长度
表示match函数匹配到的字符串的长度。AWK 的匹配函数在输入字符串中搜索给定的字符串。
例子
[jerry]$ awk 'BEGIN { if (match("One Two Three", "re")) { print RLENGTH } }'
执行此代码时,您将得到以下结果 -
输出
2
RS
它代表(输入)记录分隔符,默认值为换行符。
例子
[jerry]$ awk 'BEGIN {print "RS = " RS}' | cat -vte
执行此代码时,您将得到以下结果 -
输出
RS = $ $
启动程序
它表示由match函数匹配的字符串中的第一个位置。
例子
[jerry]$ awk 'BEGIN { if (match("One Two Three", "Thre")) { print RSTART } }'
执行此代码时,您将得到以下结果 -
输出
9
子集
它表示数组下标的分隔符,默认值为\034。
例子
[jerry]$ awk 'BEGIN { print "SUBSEP = " SUBSEP }' | cat -vte
执行此代码时,您将得到以下结果 -
输出
SUBSEP = ^\$
$0
它代表整个输入记录。
例子
[jerry]$ awk '{print $0}' marks.txt
执行此代码时,您将得到以下结果 -
输出
1) Amit Physics 80 2) Rahul Maths 90 3) Shyam Biology 87 4) Kedar English 85 5) Hari History 89
$n
它表示当前记录中的第 n个字段,字段之间用 FS 分隔。
例子
[jerry]$ awk '{print $3 "\t" $4}' marks.txt
执行此代码时,您将得到以下结果 -
输出
Physics 80 Maths 90 Biology 87 English 85 History 89
GNU AWK 特定变量
GNU AWK 特定变量如下 -
阿尔金德
它表示当前正在处理的文件在 ARGV 中的索引。
例子
[jerry]$ awk '{ print "ARGIND = ", ARGIND; print "Filename = ", ARGV[ARGIND] }' junk1 junk2 junk3
执行此代码时,您将得到以下结果 -
输出
ARGIND = 1 Filename = junk1 ARGIND = 2 Filename = junk2 ARGIND = 3 Filename = junk3
宾模式
它用于指定非 POSIX 系统上所有文件 I/O 的二进制模式。数值 1、2 或 3 分别指定输入文件、输出文件或所有文件应使用二进制 I/O。r或w的字符串值分别指定输入文件或输出文件应使用二进制 I/O。rw或wr的字符串值指定所有文件都应使用二进制 I/O。
错误号
当getline重定向失败或关闭调用失败时,字符串指示错误。
例子
[jerry]$ awk 'BEGIN { ret = getline < "junk.txt"; if (ret == -1) print "Error:", ERRNO }'
执行此代码时,您将得到以下结果 -
输出
Error: No such file or directory
场宽
设置空格分隔的字段宽度变量列表,GAWK 将输入解析为固定宽度的字段,而不是使用 FS 变量的值作为字段分隔符。
忽略大小写
设置此变量后,GAWK 将不区分大小写。以下示例演示了这一点 -
例子
[jerry]$ awk 'BEGIN{IGNORECASE = 1} /amit/' marks.txt
执行此代码时,您将得到以下结果 -
输出
1) Amit Physics 80
皮棉
它提供了GAWK 程序中--lint选项的动态控制。设置此变量后,GAWK 会打印 lint 警告。当分配字符串值 fatal 时,lint 警告将变为致命错误,与--lint=fatal完全相同。
例子
[jerry]$ awk 'BEGIN {LINT = 1; a}'
执行此代码时,您将得到以下结果 -
输出
awk: cmd. line:1: warning: reference to uninitialized variable `a' awk: cmd. line:1: warning: statement has no effect
信息处理系统
这是一个关联数组,包含有关进程的信息,例如真实有效的 UID 号、进程 ID 号等。
例子
[jerry]$ awk 'BEGIN { print PROCINFO["pid"] }'
执行此代码时,您将得到以下结果 -
输出
4316
文本域
它代表 AWK 程序的文本域。它用于查找程序字符串的本地化翻译。
例子
[jerry]$ awk 'BEGIN { print TEXTDOMAIN }'
执行此代码时,您将得到以下结果 -
输出
messages
由于en_IN区域设置,上面的输出显示英文文本
AWK - 运算符
与其他编程语言一样,AWK 也提供了大量运算符。本章通过适当的示例解释了 AWK 运算符。
编号 | 运算符和描述 |
---|---|
1 | 算术运算符
AWK 支持以下算术运算符。 |
2 | 自增和自减运算符
AWK 支持以下递增和递减运算符。 |
3 | 赋值运算符
AWK 支持以下赋值运算符。 |
4 | 关系运算符
AWK 支持以下关系运算符。 |
5 | 逻辑运算符
AWK 支持以下逻辑运算符。 |
6 | 三元运算符
我们可以使用三元运算符轻松实现条件表达式。 |
7 | 一元运算符
AWK 支持以下一元运算符。 |
8 | 指数运算符
指数运算符有两种格式。 |
9 | 字符串连接运算符
空格是一个字符串连接运算符,用于合并两个字符串。 |
10 | 数组成员运算符
它用in表示。它在访问数组元素时使用。 |
11 | 正则表达式运算符
此示例解释了正则表达式运算符的两种形式。 |
AWK - 正则表达式
AWK 在处理正则表达式方面非常强大且高效。许多复杂的任务可以用简单的正则表达式来解决。任何命令行专家都知道正则表达式的强大功能。
本章介绍标准正则表达式以及合适的示例。
点
它匹配除行尾字符之外的任何单个字符。例如,以下示例匹配fin、fun、fan等。
例子
[jerry]$ echo -e "cat\nbat\nfun\nfin\nfan" | awk '/f.n/'
执行上面的代码,你会得到以下结果 -
输出
fun fin fan
行首
它与行的开头匹配。例如,以下示例打印以模式The开头的所有行。
例子
[jerry]$ echo -e "This\nThat\nThere\nTheir\nthese" | awk '/^The/'
执行此代码时,您将得到以下结果 -
输出
There Their
行结束
它匹配行尾。例如,以下示例打印以字母n结尾的行。
例子
[jerry]$ echo -e "knife\nknow\nfun\nfin\nfan\nnine" | awk '/n$/'
输出
执行此代码时,您将得到以下结果 -
fun fin fan
匹配字符集
它用于仅匹配多个字符中的一个。例如,以下示例匹配模式Call和Tall但不匹配Ball。
例子
[jerry]$ echo -e "Call\nTall\nBall" | awk '/[CT]all/'
输出
执行此代码时,您将得到以下结果 -
Call Tall
独家套装
在独占集中,克拉否定方括号中的字符集。例如,以下示例仅打印Ball。
例子
[jerry]$ echo -e "Call\nTall\nBall" | awk '/[^CT]all/'
执行此代码时,您将得到以下结果 -
输出
Ball
改造
竖线允许对正则表达式进行逻辑“或”运算。例如,以下示例打印Ball和Call。
例子
[jerry]$ echo -e "Call\nTall\nBall\nSmall\nShall" | awk '/Call|Ball/'
执行此代码时,您将得到以下结果 -
输出
Call Ball
零次或一次出现
它匹配零次或一次出现的前一个字符。例如,以下示例匹配Color以及Color。我们通过使用?将u作为可选字符。。
例子
[jerry]$ echo -e "Colour\nColor" | awk '/Colou?r/'
执行此代码时,您将得到以下结果 -
输出
Colour Color
零次或多次出现
它匹配零个或多次出现的前一个字符。例如,以下示例匹配ca、cat、catt等。
例子
[jerry]$ echo -e "ca\ncat\ncatt" | awk '/cat*/'
执行此代码时,您将得到以下结果 -
输出
ca cat catt
一次或多次出现
它匹配前面字符的一次或多次出现。例如,下面的示例匹配一次或多次出现的2。
例子
[jerry]$ echo -e "111\n22\n123\n234\n456\n222" | awk '/2+/'
执行上面的代码,你会得到以下结果 -
输出
22 123 234 222
分组
括号 ()用于分组,字符 | 用于替代品。例如,以下正则表达式匹配包含Apple Juice 或 Apple Cake的行。
例子
[jerry]$ echo -e "Apple Juice\nApple Pie\nApple Tart\nApple Cake" | awk '/Apple (Juice|Cake)/'
执行此代码时,您将得到以下结果 -
输出
Apple Juice Apple Cake
AWK - 数组
AWK 具有关联数组,它最好的一点是 – 索引不需要是连续的数字集;您可以使用字符串或数字作为数组索引。此外,无需提前声明数组的大小 - 数组可以在运行时扩展/收缩。
其语法如下 -
句法
array_name[index] = value
其中array_name是数组的名称,index是数组索引,value是分配给数组元素的任何值。
创建数组
为了更深入地了解数组,让我们创建并访问数组的元素。
例子
[jerry]$ awk 'BEGIN { fruits["mango"] = "yellow"; fruits["orange"] = "orange" print fruits["orange"] "\n" fruits["mango"] }'
执行此代码时,您将得到以下结果 -
输出
orange yellow
在上面的例子中,我们将数组声明为fruits,其索引是水果名称,值是水果的颜色。要访问数组元素,我们使用array_name[index]格式。
删除数组元素
对于插入,我们使用赋值运算符。同样,我们可以使用delete语句从数组中删除一个元素。删除语句的语法如下 -
句法
delete array_name[index]
以下示例删除元素Orange。因此该命令不显示任何输出。
例子
[jerry]$ awk 'BEGIN { fruits["mango"] = "yellow"; fruits["orange"] = "orange"; delete fruits["orange"]; print fruits["orange"] }'
多维数组
AWK 仅支持一维数组。但是您可以使用一维数组本身轻松模拟多维数组。
例如,下面给出的是一个 3x3 二维数组 -
100 200 300 400 500 600 700 800 900
在上面的示例中,array[0][0] 存储 100,array[0][1] 存储 200,依此类推。要将 100 存储在数组位置 [0][0] 处,我们可以使用以下语法 -
句法
array["0,0"] = 100
虽然我们给出了0,0作为索引,但这不是两个索引。实际上,它只是一个带有字符串0,0 的索引。
以下示例模拟二维数组 -
例子
[jerry]$ awk 'BEGIN { array["0,0"] = 100; array["0,1"] = 200; array["0,2"] = 300; array["1,0"] = 400; array["1,1"] = 500; array["1,2"] = 600; # print array elements print "array[0,0] = " array["0,0"]; print "array[0,1] = " array["0,1"]; print "array[0,2] = " array["0,2"]; print "array[1,0] = " array["1,0"]; print "array[1,1] = " array["1,1"]; print "array[1,2] = " array["1,2"]; }'
执行此代码时,您将得到以下结果 -
输出
array[0,0] = 100 array[0,1] = 200 array[0,2] = 300 array[1,0] = 400 array[1,1] = 500 array[1,2] = 600
您还可以对数组执行各种操作,例如对其元素/索引进行排序。为此,您可以使用assort和asorti函数
AWK - 控制流
与其他编程语言一样,AWK 提供条件语句来控制程序流程。本章通过适当的示例解释了 AWK 的控制语句。
如果语句
它只是测试条件并根据条件执行某些操作。下面给出的是if语句的语法-
句法
if (condition) action
我们还可以使用下面给出的一对大括号来执行多个操作 -
句法
if (condition) { action-1 action-1 . . action-n }
例如,以下示例检查数字是否为偶数 -
例子
[jerry]$ awk 'BEGIN {num = 10; if (num % 2 == 0) printf "%d is even number.\n", num }'
执行上面的代码,你会得到以下结果 -
输出
10 is even number.
如果否则语句
在if-else语法中,我们可以提供当条件变为 false 时要执行的操作列表。
if-else语句的语法如下 -
句法
if (condition) action-1 else action-2
在上面的语法中,当条件评估为 true 时执行 action-1,当条件评估为 false 时执行 action-2。例如,以下示例检查数字是否为偶数 -
例子
[jerry]$ awk 'BEGIN { num = 11; if (num % 2 == 0) printf "%d is even number.\n", num; else printf "%d is odd number.\n", num }'
执行此代码时,您将得到以下结果 -
输出
11 is odd number.
如果-否则-如果阶梯
我们可以通过使用多个if -else 语句轻松创建if-else-if梯形图。以下示例演示了这一点 -
例子
[jerry]$ awk 'BEGIN { a = 30; if (a==10) print "a = 10"; else if (a == 20) print "a = 20"; else if (a == 30) print "a = 30"; }'
执行此代码时,您将得到以下结果 -
输出
a = 30
AWK - 循环
本章通过适当的示例解释了 AWK 的循环。循环用于以重复的方式执行一组操作。只要循环条件为真,循环就会继续执行。
For循环
for循环的语法是 -
句法
for (initialization; condition; increment/decrement) action
最初,for语句执行初始化操作,然后检查条件。如果条件为真,则执行操作,然后执行递增或递减操作。只要条件为真,循环就会继续执行。例如,以下示例使用for循环打印 1 到 5 -
例子
[jerry]$ awk 'BEGIN { for (i = 1; i <= 5; ++i) print i }'
执行此代码时,您将得到以下结果 -
输出
1 2 3 4 5
While 循环
while循环不断执行操作,直到特定的逻辑条件计算为 true 。这是while循环的语法-
句法
while (condition) action
AWK首先检查条件;如果条件为真,则执行该操作。只要循环条件计算结果为 true,就会重复此过程。例如,以下示例使用while循环打印 1 到 5 -
例子
[jerry]$ awk 'BEGIN {i = 1; while (i < 6) { print i; ++i } }'
执行此代码时,您将得到以下结果 -
输出
1 2 3 4 5
Do-While 循环
do -while循环与 while 循环类似,不同之处在于测试条件是在循环末尾评估的。这是do-while循环的语法-
句法
do action while (condition)
在do-while循环中,即使条件语句的计算结果为 false,操作语句也至少执行一次。例如,以下示例使用do-while循环打印 1 到 5 个数字 -
例子
[jerry]$ awk 'BEGIN {i = 1; do { print i; ++i } while (i < 6) }'
执行此代码时,您将得到以下结果 -
输出
1 2 3 4 5
中断声明
顾名思义,它用于结束循环执行。下面是一个当总和大于 50 时结束循环的示例。
例子
[jerry]$ awk 'BEGIN { sum = 0; for (i = 0; i < 20; ++i) { sum += i; if (sum > 50) break; else print "Sum =", sum } }'
执行此代码时,您将得到以下结果 -
输出
Sum = 0 Sum = 1 Sum = 3 Sum = 6 Sum = 10 Sum = 15 Sum = 21 Sum = 28 Sum = 36 Sum = 45
继续声明
continue语句在循环内使用以跳到循环的下一次迭代。当您希望跳过循环内某些数据的处理时,它非常有用。例如,以下示例使用continue语句打印 1 到 20 之间的偶数。
例子
[jerry]$ awk 'BEGIN { for (i = 1; i <= 20; ++i) { if (i % 2 == 0) print i ; else continue } }'
执行此代码时,您将得到以下结果 -
输出
2 4 6 8 10 12 14 16 18 20
退出声明
它用于停止脚本的执行。它接受一个整数作为参数,它是 AWK 进程的退出状态代码。如果未提供参数,退出将返回状态零。下面是当总和大于 50 时停止执行的示例。
例子
[jerry]$ awk 'BEGIN { sum = 0; for (i = 0; i < 20; ++i) { sum += i; if (sum > 50) exit(10); else print "Sum =", sum } }'
输出
执行此代码时,您将得到以下结果 -
Sum = 0 Sum = 1 Sum = 3 Sum = 6 Sum = 10 Sum = 15 Sum = 21 Sum = 28 Sum = 36 Sum = 45
让我们检查脚本的返回状态。
例子
[jerry]$ echo $?
执行此代码时,您将得到以下结果 -
输出
10
AWK - 内置函数
AWK 内置了许多可供程序员随时使用的函数。本章通过适当的示例描述算术、字符串、时间、位操作和其他杂项函数。
编号 | 内置功能及说明 |
---|---|
1 | 算术函数
AWK 具有以下内置算术函数。 |
2 | 字符串函数
AWK 具有以下内置字符串函数。 |
3 | 时间函数
AWK 具有以下内置时间函数。 |
4 | 位操作函数
AWK 具有以下内置位操作函数。 |
5 | 杂项功能
AWK 具有以下杂项功能。 |
AWK - 用户定义函数
函数是程序的基本构建块。AWK 允许我们定义自己的函数。一个大程序可以分为多个函数,每个函数可以独立编写/测试。它提供了代码的可重用性。
下面给出的是用户定义函数的一般格式 -
句法
function function_name(argument1, argument2, ...) { function body }
在此语法中,function_name是用户定义函数的名称。函数名称应以字母开头,其余字符可以是数字、字母字符或下划线的任意组合。AWK 的保留字不能用作函数名。
函数可以接受多个以逗号分隔的参数。参数不是强制性的。您还可以创建不带任何参数的用户定义函数。
函数体由一个或多个 AWK 语句组成。
让我们编写两个函数来计算最小值和最大值,并从另一个名为main的函数调用这些函数。Functions.awk文件包含 -
例子
# Returns minimum number function find_min(num1, num2){ if (num1 < num2) return num1 return num2 } # Returns maximum number function find_max(num1, num2){ if (num1 > num2) return num1 return num2 } # Main function function main(num1, num2){ # Find minimum number result = find_min(10, 20) print "Minimum =", result # Find maximum number result = find_max(10, 20) print "Maximum =", result } # Script execution starts here BEGIN { main(10, 20) }
执行此代码时,您将得到以下结果 -
输出
Minimum = 10 Maximum = 20
AWK - 输出重定向
到目前为止,我们在标准输出流上显示了数据。我们还可以将数据重定向到文件。重定向出现在print或printf语句之后。AWK 中的重定向的编写方式与 shell 命令中的重定向类似,只不过它们是在 AWK 程序内部编写的。本章通过适当的示例解释了重定向。
重定向运算符
重定向运算符的语法是 -
句法
print DATA > output-file
它将数据写入输出文件。如果输出文件不存在,则会创建一个。当使用这种类型的重定向时,在将第一个输出写入输出文件之前,输出文件将被删除。对同一输出文件的后续写入操作不会删除输出文件,而是附加到它。例如,下面的例子写Hello, World !!! 到文件。
让我们创建一个包含一些文本数据的文件。
例子
[jerry]$ echo "Old data" > /tmp/message.txt [jerry]$ cat /tmp/message.txt
执行此代码时,您将得到以下结果 -
输出
Old data
现在让我们使用 AWK 的重定向运算符将一些内容重定向到其中。
例子
[jerry]$ awk 'BEGIN { print "Hello, World !!!" > "/tmp/message.txt" }' [jerry]$ cat /tmp/message.txt
执行此代码时,您将得到以下结果 -
输出
Hello, World !!!
追加运算符
附加运算符的语法如下 -
句法
print DATA >> output-file
它将数据附加到输出文件中。如果输出文件不存在,则会创建一个。使用这种类型的重定向时,新内容将附加在文件末尾。例如,以下示例附加Hello, World !!! 到文件。
让我们创建一个包含一些文本数据的文件。
例子
[jerry]$ echo "Old data" > /tmp/message.txt [jerry]$ cat /tmp/message.txt
执行此代码时,您将得到以下结果 -
输出
Old data
现在让我们使用 AWK 的附加运算符向其附加一些内容。
例子
[jerry]$ awk 'BEGIN { print "Hello, World !!!" >> "/tmp/message.txt" }' [jerry]$ cat /tmp/message.txt
执行此代码时,您将得到以下结果 -
输出
Old data Hello, World !!!
管道
可以通过管道而不是使用文件将输出发送到另一个程序。此重定向打开一个命令管道,并通过该管道将项目的值写入另一个进程以执行该命令。重定向参数命令实际上是一个 AWK 表达式。这是管道的语法 -
句法
print items | command
让我们使用tr命令将小写字母转换为大写字母。
例子
[jerry]$ awk 'BEGIN { print "hello, world !!!" | "tr [a-z] [A-Z]" }'
执行此代码时,您将得到以下结果 -
输出
HELLO, WORLD !!!
双向通讯
AWK 可以使用|& 与外部进程进行通信,这是双向通信。例如,下面的示例使用tr命令将小写字母转换为大写字母。我们的command.awk文件包含 -
例子
BEGIN { cmd = "tr [a-z] [A-Z]" print "hello, world !!!" |& cmd close(cmd, "to") cmd |& getline out print out; close(cmd); }
执行此代码时,您将得到以下结果 -
输出
HELLO, WORLD !!!
剧本看起来很神秘吗?让我们揭开它的神秘面纱。
第一条语句cmd = "tr [az] [AZ]"是我们与 AWK 建立双向通信的命令。
下一条语句,即 print 命令,为tr命令提供输入。这里&| 表示双向通信。
第三条语句,即close(cmd, "to") ,在竞争执行后关闭to进程。
下一条语句cmd |& getline out借助 getline 函数将输出存储到 out 变量中。
下一个 print 语句打印输出,最后close函数关闭命令。
AWK - 漂亮的打印
到目前为止,我们已经使用 AWK 的print和printf函数在标准输出上显示数据。但 printf 比我们之前看到的要强大得多。该函数借用自 C 语言,在生成格式化输出时非常有用。以下是 printf 语句的语法 -
句法
printf fmt, expr-list
在上面的语法中,fmt是一个格式规范和常量的字符串。expr-list是与格式说明符对应的参数列表。
转义序列
与任何字符串类似,格式可以包含嵌入的转义序列。下面讨论的是 AWK 支持的转义序列 -
新队
以下示例使用换行符在单独的行中打印Hello和World -
例子
[jerry]$ awk 'BEGIN { printf "Hello\nWorld\n" }'
执行此代码时,您将得到以下结果 -
输出
Hello World
水平制表符
以下示例使用水平选项卡来显示不同的字段 -
例子
[jerry]$ awk 'BEGIN { printf "Sr No\tName\tSub\tMarks\n" }'
执行上面的代码,你会得到以下结果 -
输出
Sr No Name Sub Marks
垂直制表符
以下示例在每个字段后使用垂直制表符 -
例子
[jerry]$ awk 'BEGIN { printf "Sr No\vName\vSub\vMarks\n" }'
执行此代码时,您将得到以下结果 -
输出
Sr No Name Sub Marks
退格键
以下示例在除最后一个字段之外的每个字段后打印一个退格键。它会删除前三个字段中的最后一个数字。例如,Field 1显示为Field,因为最后一个字符被退格键删除。但是,最后一个字段Field 4按原样显示,因为Field 4之后没有\b。
例子
[jerry]$ awk 'BEGIN { printf "Field 1\bField 2\bField 3\bField 4\n" }'
执行此代码时,您将得到以下结果 -
输出
Field Field Field Field 4
回车
在下面的示例中,打印每个字段后,我们执行回车并在当前打印值之上打印下一个值。这意味着,在最终输出中,您只能看到Field 4,因为它是在所有先前字段之上打印的最后一个内容。
例子
[jerry]$ awk 'BEGIN { printf "Field 1\rField 2\rField 3\rField 4\n" }'
执行此代码时,您将得到以下结果 -
输出
Field 4
换页
以下示例在打印每个字段后使用换页符。
例子
[jerry]$ awk 'BEGIN { printf "Sr No\fName\fSub\fMarks\n" }'
执行此代码时,您将得到以下结果 -
输出
Sr No Name Sub Marks
格式说明符
与 C 语言一样,AWK 也有格式说明符。AWK 版本的 printf 语句接受以下转换规范格式 -
%C
它打印一个字符。如果用于%c 的参数是数字,则将其视为字符并打印。否则,假定参数是字符串,并且打印该字符串的唯一第一个字符。
例子
[jerry]$ awk 'BEGIN { printf "ASCII value 65 = character %c\n", 65 }'
输出
执行此代码时,您将得到以下结果 -
ASCII value 65 = character A
%d 和 %i
它仅打印小数的整数部分。
例子
[jerry]$ awk 'BEGIN { printf "Percentags = %d\n", 80.66 }'
执行此代码时,您将得到以下结果 -
输出
Percentags = 80
%e 和 %E
它打印 [-]d.dddddde[+-]dd 形式的浮点数。
例子
[jerry]$ awk 'BEGIN { printf "Percentags = %E\n", 80.66 }'
执行此代码时,您将得到以下结果 -
输出
Percentags = 8.066000e+01
% E格式使用E而不是 e。
例子
[jerry]$ awk 'BEGIN { printf "Percentags = %e\n", 80.66 }'
执行此代码时,您将得到以下结果 -
输出
Percentags = 8.066000E+01
%F
它打印 [-]ddd.dddddd 形式的浮点数。
例子
[jerry]$ awk 'BEGIN { printf "Percentags = %f\n", 80.66 }'
执行此代码时,您将得到以下结果 -
输出
Percentags = 80.660000
%g 和 %G
使用 %e 或 %f 转换(以较短者为准),并抑制非有效零。
例子
[jerry]$ awk 'BEGIN { printf "Percentags = %g\n", 80.66 }'
输出
执行此代码时,您将得到以下结果 -
Percentags = 80.66
%G格式使用%E而不是 %e。
例子
[jerry]$ awk 'BEGIN { printf "Percentags = %G\n", 80.66 }'
执行此代码时,您将得到以下结果 -
输出
Percentags = 80.66
%o
它打印一个无符号的八进制数。
例子
[jerry]$ awk 'BEGIN { printf "Octal representation of decimal number 10 = %o\n", 10}'
执行此代码时,您将得到以下结果 -
输出
Octal representation of decimal number 10 = 12
%u
它打印一个无符号的十进制数。
例子
[jerry]$ awk 'BEGIN { printf "Unsigned 10 = %u\n", 10 }'
执行此代码时,您将得到以下结果 -
输出
Unsigned 10 = 10
%s
它打印一个字符串。
例子
[jerry]$ awk 'BEGIN { printf "Name = %s\n", "Sherlock Holmes" }'
执行此代码时,您将得到以下结果 -
输出
Name = Sherlock Holmes
%x 和 %X
它打印一个无符号的十六进制数。% X格式使用大写字母而不是小写字母。
例子
[jerry]$ awk 'BEGIN { printf "Hexadecimal representation of decimal number 15 = %x\n", 15 }'
执行此代码时,您将得到以下结果 -
输出
Hexadecimal representation of decimal number 15 = f
现在让我们使用 %X 并观察结果 -
例子
[jerry]$ awk 'BEGIN { printf "Hexadecimal representation of decimal number 15 = %X\n", 15 }'
执行此代码时,您将得到以下结果 -
输出
Hexadecimal representation of decimal number 15 = F
%%
它打印单个%字符并且不转换任何参数。
例子
[jerry]$ awk 'BEGIN { printf "Percentags = %d%%\n", 80.66 }'
执行此代码时,您将得到以下结果 -
输出
Percentags = 80%
带 % 的可选参数
对于%,我们可以使用以下可选参数 -
宽度
该字段被填充到宽度。默认情况下,该字段用空格填充,但当使用 0 标志时,它用零填充。
例子
[jerry]$ awk 'BEGIN { num1 = 10; num2 = 20; printf "Num1 = %10d\nNum2 = %10d\n", num1, num2 }'
执行此代码时,您将得到以下结果 -
输出
Num1 = 10 Num2 = 20
前导零
前导零充当标志,表示输出应该用零而不是空格填充。请注意,此标志仅在字段比要打印的值宽时才有效。下面的例子描述了这一点 -
例子
[jerry]$ awk 'BEGIN { num1 = -10; num2 = 20; printf "Num1 = %05d\nNum2 = %05d\n", num1, num2 }'
执行此代码时,您将得到以下结果 -
输出