3

我正在阅读GNU Awk 用户指南 → 7.5.2 传达信息的内置PROCINFO变量中的内置变量的定义:

程序信息#

该数组的元素提供对有关正在运行的 awk 程序的信息的访问。以下元素(按字母顺序列出)保证可用:

PROCINFO["FS"]

这是"FS"如果字段拆分FS有效,"FIELDWIDTHS"字段拆分FIELDWIDTHS有效,"FPAT"字段匹配FPAT有效,或者"API"字段拆分由 API 输入解析器控制。

是的,它运作良好。当我提供字符串“hello;you”并按顺序设置FS为“;”、FIELDWIDTHS“2 2”和FPAT三个字符时,请参阅此示例:

$ gawk 'BEGIN{FS=";"}{print PROCINFO["FS"]; print $1}' <<< "hello;you"
FS
hello
$ gawk 'BEGIN{FIELDWIDTHS="2 2 2"}{print PROCINFO["FS"]; print $1}' <<< "hello;you"
FIELDWIDTHS
he
$ gawk 'BEGIN{FPAT="..."}{print PROCINFO["FS"]; print $1}' <<< "hello;you"
FPAT
hel

这很好,效果很好。

他们在4.8 Checking How gawk Is Splitting Records中提到之前的一点:

为了判断哪种类型的字段拆分有效,请使用PROCINFO["FS"](请参阅传递信息的内置变量部分)。该值是"FS"如果正在使用常规字段拆分,是否正在使用"FIELDWIDTHS"固定宽度的字段拆分,或者"FPAT"是否正在使用基于内容的字段拆分。

而且在更改 FS 不影响字段中,他们描述了更改如何影响下一条记录

根据 POSIX 标准,awk 应该表现得好像每条记录在读取时都被拆分为字段。特别是,这意味着如果您在FS读取记录后更改 的值,则字段的值(即,它们是如何拆分的)应该反映 的旧值FS,而不是新值。

这个案例很好的解释了:

$ gawk 'BEGIN{FS=";"} {FS="|"; print $1}' <<< "hello;you
bye|everyone"
hello  # "hello;you" is splitted using FS=";", the assignment FS="|" doesn't affect it yet
bye    # "bye|everyone" is splitted using FS="|"

考虑到所有这些,我认为这PROCINFO["FS"]将始终反映"FS"为正在打印的记录中的字段拆分。
但是,请参阅此案例:

$ gawk 'BEGIN{FPAT="..."}{FS=";"; print PROCINFO["FS"]; print $1}' <<< "hello;you"
FS
hel

PROCINFO["FS"]显示当前记录 (FS) 中设置的信息,而不是 Awk 在处理数据时考虑的信息(即 FPAT)。如果我们交换分配,也会发生同样的情况:

$ gawk 'BEGIN{FS=";"}{FPAT="..."; print PROCINFO["FS"]; print $1}' <<< "hello;you"
FPAT
hello

为什么PROCINFO["FS"]显示的 FS 与打印它的记录中使用的 FS 不同?

4

1 回答 1

2

字段拆分(使用 FS、FIELDWIDTHS 或 FPAT)发生在读取记录或$0作为一个整体被赋予新值(例如$0="foo"sub(/foo/,"bar"))时。print PROCINFO["FS"]告诉您PROCINFO["FS"] 当前具有的值不一定与上次发生字段拆分时的值相同。

和:

$ gawk 'BEGIN{FPAT="..."}{FS=";"; print PROCINFO["FS"]; print $1}' <<< "hello;you"
FS
hel

您在已经基于 填充FS=";" 之后 进行设置,然后打印新值(将在下次将记录拆分为字段时使用),然后打印在您设置之前填充的值。$1FPAT="..."PROCINFO["FS"]$1FS=";"

如果将其设置$0为自身,则字段拆分将再次发生,这次使用新的 FS 值而不是原始 FPAT 值:

$ gawk 'BEGIN{FPAT="..."}{FS=";"; print PROCINFO["FS"]; print $1; $0=$0; print $1}' <<< "hello;you"
FS
hel
hello
于 2021-01-10T22:32:40.397 回答