【问题标题】:How does PROCINFO show info on FS on the specific record?PROCINFO 如何在特定记录上显示 FS 信息?
【发布时间】: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)。

标签: awk gnu


【解决方案1】:

字段拆分(使用 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=";" $1 已经基于FPAT="..." 填充,然后打印PROCINFO["FS"] 新值(将在下一次使用 一条记录被拆分为多个字段),然后打印在您设置FS=";" 之前填充的$1 的值。

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

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

【讨论】:

    猜你喜欢
    • 2010-09-06
    • 1970-01-01
    • 2014-05-24
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多