当前位置: 首页 > news >正文

第5.1节:awk内置变量

1 第5.1节:awk内置变量

1.1 控制型变量

以下是按字母顺序排列的变量列表,你可通过修改这些变量来控制 awk 执行某些操作的方式。

特定于 gawk 的变量会标记有井号(# )。这些变量属于 gawk 的扩展特性。在其他 awk 实现中,或者当 gawk 处于兼容模式时,它们不会有特殊作用(每个变量的描述中会注明任何例外情况 )。

1.1.1 BINMODE

在非 POSIX 系统上,此变量指定对所有 I/O 使用二进制模式。数值为 1、2 或 3 时,分别表示输入文件、输出文件或所有文件应使用二进制 I/O 。数值小于 0 会被视为 0 ,数值大于 3 会被视为 3 。另外,字符串值 "r""w" 分别表示输入文件和输出文件应使用二进制 I/O 。字符串值 "rw""wr" 表示所有文件都应使用二进制 I/O 。任何其他字符串值会被当作 "rw" 处理,但会导致 gawk 生成一条警告消息。mawk也支持此变量,但仅支持使用数值。

1.1.2 CONVFMT

一个用于控制数字转换为字符串的规则的字符串,其工作方式实际上是,作为第一个参数传递给 sprintf() 函数。它的默认值是 "%.6g"CONVFMT 是由 POSIX 标准引入的。

1.1.3 FIELDWIDTHS

由空格分隔的列宽度列表,告知gawk如何按固定列边界拆分输入。从版本4.2开始,每个字段宽度前可选择性地加上由冒号分隔的值,用于指定字段开始前要跳过的字符数。为FIELDWIDTHS赋值会覆盖FSFPAT在字段拆分方面的作用 。

1.1.4 FPAT

一个正则表达式(以字符串形式),告知gawk根据匹配该正则表达式的文本来创建字段。为FPAT赋值会覆盖FSFIELDWIDTHS在字段拆分方面的作用。

1.1.5 FS

输入字段分隔符。其值可以是单字符字符串,也可以是多字符正则表达式,用于匹配记录中字段间的分隔符。若值为空字符串("" ),则记录中的每个字符都会成为单独的字段(此行为是gawk的扩展特性,POSIX awk未规定FS为空字符串时的行为。不过,其他一些awk版本也会特殊处理"" )。

默认值是 " " ,即由单个空格组成的字符串。作为特殊例外,此值意味着任意空格、制表符和/或换行符序列都算作一个分隔符,且记录开头和结尾的空格、制表符及换行符会被忽略。

你可通过命令行的-F选项设置FS的值,例如:

awk -F, 'program' input-files

gawk正使用FIELDWIDTHSFPAT进行字段拆分,为FS赋值会让gawk恢复为基于FS的常规字段拆分方式。简单执行FS = FS(可附带解释性注释 )就能轻松实现这一点。

1.1.6 IGNORECASE

IGNORECASE为非零值或非空值,那么所有字符串比较以及所有正则表达式匹配都会不区分大小写。这适用于正则表达式匹配操作符~!~gensub()gsub()index()match()patsplit()split()以及sub()函数,也适用于记录终止符RS的匹配,还有基于FSFPAT的字段拆分。不过,IGNORECASE的值不会影响数组下标,也不会影响使用单字符字段分隔符时的字段拆分。

1.1.7 LINT

当此变量为真(非零或非空)时,gawk的行为等同于启用--lint命令行选项(。若值为"fatal"lint警告会变为致命错误;若值为"invalid",仅会发出关于实际无效内容的警告(此功能尚未完全实现 )。任何为真的值都会打印非致命警告。为LINT赋假值会关闭lint警告。

此变量是gawk的扩展特性,在其他awk实现中无特殊作用。与其他特殊变量不同,即便gawk处于兼容模式,修改LINT也会影响lint警告的产生,就像 --lint--traditional 选项可独立控制 gawk 行为的不同方面一样,程序执行期间对 lint 警告的控制,与正在运行的 awk 实现风格无关 。

(说明:--lint 用于开启代码检查类警告,--traditionalgawk 兼容传统 awk 行为;“flavor of awk” 意译为 “awk 实现风格” ,体现不同 awk 变体的特性 )

1.1.8 OFMT

控制使用 print 语句打印时,数字转换为字符串的格式。其工作方式是作为第一个参数传递给 sprintf() 函数。它的默认值是 "%.6g" 。早期版本的 awkOFMT 指定一般表达式中数字转字符串的格式;现在这项功能由 CONVFMT 实现 。

1.1.9 OFS

输出字段分隔符。print 语句输出时,会在字段之间插入该分隔符。它的默认值是 " " ,即由单个空格组成的字符串 。

1.1.10 ORS

输出记录分隔符。每个 print 语句执行结束时会输出它。默认值是 "\n" ,即换行符 。

1.1.11 PREC

任意精度浮点数运算时使用的工作精度,默认是 53 位 。

1.1.12 ROUNDMODE

用于任意精度算术运算的舍入模式,默认是 "N"(对应 IEEE 754 标准中的 roundTiesToEven;

1.1.13 RS

输入记录分隔符。默认值是包含单个换行符的字符串,这意味着一个输入记录就是文本中的一行。它也可以是空字符串,此时记录由连续的空行分隔。若它是正则表达式,记录则由匹配该正则表达式的输入文本分隔。RS 支持正则表达式是 gawk 的扩展特性。在大多数其他 awk 实现中,或者当 gawk 处于兼容模式时,只会使用 RS 值的第一个字符 。

1.1.14 SUBSEP

下标分隔符。默认值是 "\034" ,用于分隔多维数组下标的各部分。因此,表达式 foo["A", "B"] 实际访问的是 foo["A\034B"]

1.1.15 TEXTDOMAIN

用于在 awk 层面实现程序的国际化。它为源代码中经过特殊标记的字符串常量设置默认文本域,也用于 dcgettext()dngettext()bindtextdomain() 函数(。TEXTDOMAIN 的默认值是 "messages"

1.2 用于传递信息的内置变量

  以下是按字母顺序排列的变量列表,awk 会在特定情况下自动设置这些变量,以便向你的程序传递信息。

特定于 gawk 的变量会用井号(# )标记。这些变量是 gawk 的扩展特性。在其他 awk 实现中,或者当 gawk 处于兼容模式时,它们不会有特殊含义:

1.2.1 ARGC、ARGV

awk 程序可用的命令行参数存储在一个名为 ARGV 的数组中。ARGC 是命令行参数的数量。与大多数 awk 数组不同,ARGV 的索引从 0 到 ARGC - 1 。看以下示例:

$ awk 'BEGIN {for (i = 0; i < ARGC; i++)print ARGV[i]}' inventory-shipped mail-list
-| awk
-| inventory-shipped
-| mail-list

ARGV[0] 包含 awkARGV[1] 包含 inventory-shippedARGV[2] 包含 mail-listARGC 的值是 3 ,比 ARGV 最后一个元素的索引大 1 ,因为元素是从 0 开始编号的。

ARGCARGV 的命名,以及数组索引从 0 到 ARGC - 1 的惯例,源自 C 语言访问命令行参数的方式。

ARGV[0] 的值在不同系统上可能不同。另外要注意,程序文本不会包含在 ARGV 中,awk 的任何命令行选项也不会。想了解 awk 如何使用这些变量 。

1.2.2 ARGIND

当前正在处理文件在 ARGV 中的索引。每当 gawk 打开一个新数据文件进行处理时,会将 ARGIND 设置为该文件名在 ARGV 中的索引。当 gawk 处理输入文件时,FILENAME == ARGV[ARGIND] 始终为真。

此变量在文件处理中很有用:它能让你知晓在数据文件列表中处理到了什么位置,还能区分命令行上连续出现的同名文件实例。

虽然你可在 awk 程序中修改 ARGIND 的值,但 gawk 打开下一个文件时,会自动将其设为新值。

1.2.3 ENVIRON

一个关联数组,包含环境变量的值;数组索引是环境变量的名称,元素是对应环境变量的值。例如,ENVIRON["HOME"] 的值可能是 /home/arnold

对于 POSIX awk ,修改此数组不会影响传递给 awk 衍生出的程序的环境(通过重定向或 system() 函数 )。不过,从版本 4.2 开始,若 gawk 处于非 POSIX 兼容模式,修改 ENVIRON 时,gawk 会更新自身环境,进而改变它创建的程序所看到的环境。因此,你若在 gawk 中修改 ENVIRON ,要留意对后续衍生程序环境的影响。因此,如果你修改 ENVIRON["PATH"] 时应格外小心,因为它是查找可执行程序的搜索路径。

这也可能会影响正在运行的 gawk 程序,因为某些内置函数可能会关注特定的环境变量。最显著的例子是 mktime(),在许多系统上,它会关注 TZ 环境变量的值。

有些操作系统可能没有环境变量。在这类系统上,ENVIRON 数组是空的(ENVIRON["AWKPATH"]ENVIRON["AWKLIBPATH"] 除外。

1.2.4 ERRNO

若在为 getline 进行重定向期间、getline 读取期间,或者 close() 操作期间发生系统错误,ERRNO 会包含一个描述该错误的字符串。

此外,gawk 在打开每个命令行输入文件前,会清空 ERRNO 。这使得可以在 BEGINFILE 模式中检查文件是否可读。

除此之外,ERRNO 的工作方式类似于 C 语言的 errno 变量。除了刚提到的情况,gawk 从不会清空它(设为 0 或空字符串 "" )。因此,只有当 I/O 操作返回失败值(比如 getline 返回 -1 )时,你才应期望它的值有意义。当然,你完全可以在执行 I/O 操作前自行清空它。

ERRNO 的值对应 C 语言 errno 变量中的系统错误,PROCINFO["errno"] 会被设为 errno 的值。对于非系统错误,PROCINFO["errno"] 会是 0 。

1.2.5 FILENAME

当前输入文件的名称。当命令行上未列出数据文件时,awk 从标准输入读取,此时 FILENAME 被设为 "-"

每次读取新文件时,FILENAME 会改变。在 BEGIN 规则中,FILENAME 的值是空字符串 "" ,因为此时还未处理任何输入文件。不过要注意,在 BEGIN 规则中使用 getline,可能会为 FILENAME 赋予一个值。

1.2.6 FNR

当前文件中的当前记录号。awk 每次读取一条新记录时,会递增 FNR

awk 每次开始处理一个新输入文件时,会将 FNR 重置为 0 。

1.2.7 NF

当前输入记录的字段数量。每当读取一条新记录、创建一个新字段,或者 $0 发生变化时,NF 会被设置。

与本小节描述的大多数变量不同,为 NF 赋值有可能影响 awk 的内部运作。具体而言,对 NF 赋值可用于在当前记录中创建字段或删除字段。

1.2.8 PROCINFO

该数组的元素可用于获取关于正在运行的 awk 程序的信息。以下元素(按字母顺序列出 )保证可用:

1.2.8.1 PROCINFO[“argv”]

PROCINFO["argv"] 数组包含所有命令行参数(在支持通配符扩展和重定向处理的平台上,这些处理是程序需手动完成的 ),下标范围从 0 到 argc - 1 。例如,PROCINFO["argv"][0] 会包含调用 gawk 时所用的名称。以下是一个说明该特性用法的示例:

gawk '
BEGIN {for (i = 0; i < length(PROCINFO["argv"]); i++)print i, PROCINFO["argv"][i]
}'

请注意,这与标准 ARGV 数组不同,标准 ARGV 数组不包含已被 gawk 处理过的命令行参数。

1.2.8.2 PROCINFO[“egid”]

getegid() 系统调用的返回值。

1.2.8.3 PROCINFO[“errno”]

ERRNO 被设为相关错误消息时,C 语言 errno 变量的值。

1.2.8.4 PROCINFO[“euid”]

geteuid() 系统调用的返回值。

1.2.8.5 PROCINFO[“FS”]

若当前是用 FS 进行字段拆分,值为 "FS" ;若用 FIELDWIDTHS 进行字段拆分,值为 "FIELDWIDTHS" ;若用 FPAT 进行字段匹配拆分,值为 "FPAT" ;若字段拆分由 API 输入解析器控制,值为 "API"

1.2.9 PROCINFO[“gid”]

getgid() 系统调用的返回值。

1.2.10 PROCINFO[“identifiers”]

一个子数组,下标为 awk 程序文本中使用的所有标识符名称。标识符指的是变量(无论是标量还是数组 )、内置函数、用户定义函数或扩展函数的名称。对于每个标识符,该元素的值为以下之一:

  • "array":标识符是数组。
  • "builtin":标识符是内置函数。
  • "extension":标识符是通过 @load-l 加载的扩展函数。
  • "scalar":标识符是标量。
  • "untyped":标识符无类型(可作为标量或数组使用;gawk 尚未确定其类型 )。
  • "user":标识符是用户定义函数。

这些值表示 gawk 解析完程序后对标识符的认知;程序运行期间不会更新。

1.2.10.1 PROCINFO[“platform”]

此元素提供一个字符串,表明 gawk 编译所针对的平台。其值为以下之一:

  • "mingw":Microsoft Windows,使用 MinGW 编译。
  • "os390":OS/390(也称为 z/OS )。
  • "posix":GNU/Linux、Cygwin、macOS 以及传统类 Unix 系统。
  • "vms":OpenVMS。
1.2.10.2 PROCINFO[“pgrpid”]

当前进程的进程组 ID 。

1.2.10.3 PROCINFO[“pid”]

当前进程的进程 ID 。

1.2.10.4 PROCINFO[“pma”]

编译到 gawk 中的 PMA 内存分配器的版本。若 PMA 分配器不可用,此元素不存在。

1.2.10.5 PROCINFO[“ppid”]

当前进程的父进程 ID 。

1.2.10.6 PROCINFO[“strftime”]

strftime() 函数的默认时间格式字符串。为此元素赋值会改变默认格式。

1.2.10.7 PROCINFO[“uid”]

getuid() 系统调用的返回值。

1.2.10.8 PROCINFO[“version”]

gawk 的版本。

以下额外数组元素可在你的 gawk 版本支持任意精度算术运算时,提供关于 MPFR 和 GMP 库的信息:

1.2.10.9 PROCINFO[“gmp_version”]

GNU MP 库的版本。

1.2.10.10 PROCINFO[“mpfr_version”]

GNU MPFR 库的版本。

1.2.10.11 PROCINFO[“prec_max”]

MPFR 支持的最大精度。

1.2.10.12 PROCINFO[“prec_min”]

MPFR 要求的最小精度。

以下额外数组元素可在你的 gawk 版本支持动态加载扩展函数时,提供关于扩展 API 版本的信息:

1.2.10.13 PROCINFO[“api_major”]

扩展 API 的主版本号。

1.2.10.14 PROCINFO[“api_minor”]

扩展 API 的次版本号。

在部分系统中,数组里可能有 "group1""groupN"N 为某个数 )形式的元素。N 是进程所属补充组的数量。可使用 in 运算符测试这些元素是否存在。

以下元素可用于改变 gawk 的行为:

1.2.10.15 PROCINFO[“BUFFERPIPE”]

若此元素存在,所有输出到管道的内容会被缓冲。

1.2.10.16 PROCINFO[“command”, “BUFFERPIPE”]

使输出到指定命令的内容被缓冲。

1.2.10.17 PROCINFO[“NONFATAL”]

若此元素存在,所有重定向操作的 I/O 错误会变为非致命错误。

1.2.10.18 PROCINFO[“name”, “NONFATAL”]

使针对 name 的 I/O 错误变为非致命错误。

1.2.10.19 PROCINFO[“command”, “pty”]

若要与 command 进行双向通信,使用伪终端(pseudo-tty )而非建立双向管道。

1.2.10.20 PROCINFO[“input_name”, “READ_TIMEOUT”]

为从输入重定向 input_name 读取数据设置超时时间。

1.2.10.21 PROCINFO[“input_name”, “RETRY”]

input_name 读取数据时,若发生可重试的 I/O 错误,且此数组项存在,getline 会返回 -2 ,而非默认返回 -1 并将 input_name 配置为不再返回数据。当 errno 值为 EAGAINEWOULDBLOCKEINTRETIMEDOUT 时,I/O 错误可重试。此特性与 PROCINFO["input_name", "READ_TIMEOUT"] 配合使用,或在文件描述符被配置为非阻塞模式的场景中可能有用。

1.2.10.22 PROCINFO[“sorted_in”]

PROCINFO 中存在此元素,其值会控制 for (indx in array) 循环处理数组下标的顺序。这是一项高级特性,完整说明将延后;

1.2.11 RLENGTH

match() 函数匹配到的子字符串长度。调用 match() 函数会设置 RLENGTH ,其值为匹配字符串的长度,若未找到匹配则为 -1 。

1.2.12 RSTART

match() 函数匹配到的子字符串的起始字符索引。调用 match() 函数会设置 RSTART ,其值为字符串中匹配子字符串的起始位置,若未找到匹配则为 0 。

1.2.13 RT

每次读取一条记录时,若文本匹配记录分隔符 RS 指定的内容,RT 会被设置为该匹配文本。

1.2.14 SYMTAB

一个数组,其下标为程序中所有已定义的全局变量和数组的名称。SYMTABgawk 的符号表对 awk 程序员可见。gawk 解析程序时构建该数组,程序开始运行前就已完整。

此数组可用于间接访问变量的值(读或写 ):

foo = 5SYMTAB["foo"] = 4
print foo  # 输出 4

isarray() 函数可用于测试 SYMTAB 中的元素是否为数组。另外,不能对 SYMTAB 数组使用 delete 语句。

gawk 5.0 版本之前,你可以对 SYMTAB 使用未预定义的下标,例如:

SYMTAB["xxx"] = 5
print SYMTAB["xxx"]

但这种用法现已失效,会产生致命错误,因为它曾导致严重混乱。

SYMTAB 数组比表面看起来更有意思。Andrew Schorr 指出,它实际上为 awk 提供了“数据指针”功能。看他的示例:

# 通过间接方式将任意变量乘以指定数值并返回结果
function multiply(variable, amount)
{return SYMTAB[variable] *= amount
}# 使用示例
BEGIN {answer = 10.5multiply("answer", 4)print "The answer is", answer
}

运行结果:

$ gawk -f answer.awk
The answer is 42

注意:为避免严重的“时间旅行悖论”,FUNCTABSYMTAB 都不能作为 SYMTAB 数组的元素。

1.2.15 关于 NR 和 FNR 的修改

awk 每次读取一条新记录时,会递增 NRFNR ,而非将它们设为已读记录数量的绝对值。这意味着程序可修改这些变量,且后续每条记录读取时,新值会继续递增。以下示例展示了这一点:

$ echo '1'
> 2
> 3
> 4' | awk 'NR == 2 { NR = 17 }
> { print NR }'
-| 1
-| 17
-| 18
-| 19

FNR 被加入 awk 语言之前,许多 awk 程序利用此特性,在 FILENAME 改变时将 NR 重置为 0 ,以此跟踪文件中的记录数量。

1.2.16 使用 ARGC 和 ARGV

以下代码打印出包含在 ARGCARGV 中的信息:

$ awk 'BEGIN {for (i = 0; i < ARGC; i++)print ARGV[i]}' inventory-shipped mail-list
-| awk
-| inventory-shipped
-| mail-list

在此示例中,ARGV[0] 包含 awkARGV[1] 包含 inventory-shippedARGV[2] 包含 mail-list 。注意,awk 程序本身不会加入 ARGV 。其他命令行选项及其参数也不会加入,包括用 -v 选项进行的变量赋值。命令行上的常规变量赋值会被当作参数,显示在 ARGV 数组中。假设有一个名为 showargs.awk 的文件,内容如下:

BEGIN {printf "A=%d, B=%d\n", A, Bfor (i = 0; i < ARGC; i++)printf "\tARGV[%d] = %s\n", i, ARGV[i]
}
END { printf "A=%d, B=%d\n", A, B }

运行它会产生如下结果:

$ awk -v A=1 -f showargs.awk B=2 /dev/null
-| A=1, B=0-| 	ARGV[0] = awk
-| 	ARGV[1] = B=2
-| 	ARGV[2] = /dev/null
-| A=1, B=2

程序可修改 ARGCARGV 的元素。每当 awk 处理完一个输入文件,会使用 ARGV 的下一个元素作为下一个输入文件的名称。通过在 ARGV 中存储不同字符串,程序可改变要读取的文件。用 "-" 表示标准输入。存储额外元素并递增 ARGC 会使更多文件被读取。

若减小 ARGC 的值,会从列表末尾移除输入文件。程序可将 ARGC 的旧值记录到其他地方,把被移除的参数当作非文件名的内容处理。

要从列表中间移除文件,可在 ARGV 中对应文件名称的位置存入空字符串("" )。作为特殊特性,awk 会忽略被替换为空字符串的文件名。另一种方式是使用 delete 语句从 ARGV 中移除元素

所有这些操作通常在 BEGIN 规则中完成,即在实际处理输入开始前。了解从 ARGV 移除元素的不同方式示例。

要真正把选项传入 awk 程序,需用 -- 结束 awk 选项,然后在后续提供 awk 程序的选项,如下:

awk -f myprog.awk -- -v -q file1 file2 ...

以下代码片段会处理 ARGV ,检查并移除前面提到的命令行选项:

BEGIN {for (i = 1; i < ARGC; i++) {if (ARGV[i] == "-v")verbose = 1else if (ARGV[i] == "-q")debug = 1else if (ARGV[i] ~ /^-./) {e = sprintf("%s: unrecognized option -- %c",ARGV[0], substr(ARGV[i], 2, 1))print e > "/dev/stderr"} elsebreakdelete ARGV[i]}
}

gawk 中,用 -- 结束 awk 选项并非必需。除非指定了 --posix ,否则 gawk 会悄悄将任何无法识别的选项放入 ARGV ,供 awk 程序处理。一旦遇到未知选项,gawk 会停止查找其他可能识别的选项。前面带 gawk 的命令行示例如下:

gawk -f myprog.awk -q -v file1 file2 ...

因为 -q 不是有效的 gawk 选项,它和后面的 -v 会被传递给 awk 程序

设计程序时,应选择不会与 gawk 冲突的选项,因为 gawk 会先处理它能识别的选项,再将剩余命令行内容传递给你的程序。结合 -E 选项使用 #! 可能会有帮助


作者声明:本文用于记录和分享作者的学习心得,可能有部分文字或示例来自AI平台,如:豆包、DeepSeek(硅基流动)(注册链接)等,由于本人水平有限,难免存在表达错误,欢迎留言交流和指教!
Copyright © 2022~2025 All rights reserved.

http://www.dtcms.com/a/343279.html

相关文章:

  • MySQL诊断系列(5/6):表结构与元数据查询——快速掌握数据库“DNA”
  • 在pycharmIDE中如何快速掌握一个新模块的使用方法
  • 前端视频流处理从 0 到 “能跑”:可复制 Demo+WebGL/Worker 优化,覆盖会议 / 直播 / 监控场景
  • js来比较两个对象内容有误差异
  • 从源码中学习Java面向对象的多态
  • 通过自定义域名访问内网的web服务和tcp应用:内网ip到局域网外域名访问过程
  • 使用Docker部署Coze Studio开源版
  • (亲测)Centos7升级gcc 9
  • XTDrone——无人机基于2D激光Lidar进行二维运动规划(细节提醒以及相关报错解决)
  • 嵌入式-中断的概念,优先级,编程-Day17
  • 高效研发管理新选择:Codes 一站式平台深度解析
  • 6.Shell脚本修炼手册---grep命令使用指南
  • 定时器(Timer)和延时器
  • 文化遗产数字化对手持SLAM设备有哪些特殊要求?
  • 使用 X11 转发服务器界面
  • linux安装mysql ndb cluster
  • 牛客:链表分割算法详解
  • Java设计模式-享元模式
  • FreeRTOS学习笔记(三)--汇编指令
  • C ++代码学习笔记(一)
  • Layui 中的 iframe 详解与最佳实践
  • Linux笔记7——shell编程基础-1
  • SMT车间如何通过防静电监控系统提升产品质量
  • 206.反转链表
  • 【时时三省】vectorCAST 便捷使用技巧
  • 利用 Python 爬虫获取淘宝商品评论实战指南
  • 并发编程原理与实战(二十五)手写简易线程池实战,剖析线程状态转换过程
  • 【LINUX网络】UDP协议基础原理
  • Netty AdaptiveRecvByteBufAllocator原理详解
  • 分布式消息队列技术(原理相关):Kafka