【发布时间】:2021-01-11 22:15:11
【问题描述】:
我正在阅读GNU Awk User's Guide → 7.5.2 Built-in Variables That Convey Information 上的PROCINFO 内置变量的定义:
PROCINFO #
此数组的元素提供对有关正在运行的 awk 程序的信息的访问。以下元素(按字母顺序列出)保证可用:
PROCINFO["FS"]这是
"FS",如果与FS的字段拆分有效,"FIELDWIDTHS"如果与FIELDWIDTHS的字段拆分有效,"FPAT"如果与FPAT的字段匹配有效,或@987654333 @如果字段拆分由 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"](参见Built-in Variables That Convey Information 部分)。如果使用常规字段拆分,则值为"FS",如果使用固定宽度字段拆分,则值为"FIELDWIDTHS",如果使用基于内容的字段拆分,则值为"FPAT"。
并且还在Changing FS Does Not Affect the Fields 中描述了这些更改如何影响下一条记录:
根据 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 不同?
【问题讨论】:
-
@luciole75w 完全正确!这是正确的行为,并在文档中进行了描述。但是,PROCINFO 确实会立即更改,这是不一致的。这是令我惊讶的问题和问题的原因(不确定我是否表达得足够清楚,请随时编辑!)
-
sry,我读你的帖子太快了:/
-
阅读您的问题时,我确实认为您提出的行为和您引用的文档是一致的。
PROCINFO["FS"]返回有效的值,即将要使用的值,而不是已经使用的值。 -
您希望能够提取已用于拆分的信息。那也很有用。但是,如果您将 first 操作读取为
{fs=PROCINFO["fs"]},则此信息最终可用。这将始终是用于拆分正在处理的当前记录的值。重新分配任何字段或记录时也是如此。如果您执行{$1=$1; fs=PROCINFO["fs"]}或{$0="string"; fs=PROCINFO["fs"]},则字符串fs将始终为您提供用于拆分当前活动记录$0的值。显然,这需要更多的实现。 -
@fedorqui'SOstopharming' 我认为您的困惑在于认为字段拆分是在处理记录期间发生的事情,因此在处理当前记录期间会应用 FS 值。事实并非如此。当 $0 被赋值时,会使用 FS 的当前值进行字段拆分。句号,句号。您可以在处理当前记录期间将 FS 的值更改 20 次,它对字段拆分没有影响,但 PROCINFO[FS] 总是简单地反映当时设置的 FS(或 FPAT 或 FIELDWIDTHS)。