我正在阅读 GNU Awk User's Guide → 7.5.2 Built-in Variables That Convey Information 上的 PROCINFO
内置变量的定义:
PROCINFO #
此数组的元素提供对有关正在运行的 awk 程序的信息的访问。以下元素(按字母顺序排列)保证可用:
PROCINFO["FS"]
如果使用 "FS"
进行字段拆分有效,则为 FS
,如果使用 "FIELDWIDTHS"
进行字段拆分有效,则为 FIELDWIDTHS
,如果与"FPAT"
有效,如果字段拆分由 API 输入解析器控制,则为 FPAT
。
是的,它工作得很好。当我提供字符串 "hello;you" 并按顺序将 "API"
设置为 ";"、FS
为 "2 2 " 和 FIELDWIDTHS
为三个字符时,请参阅此示例:
FPAT
这很好,效果很好。
他们在4.8 Checking How gawk Is Splitting Records中提到之前的那个:
<块引用>要判断哪种字段拆分有效,请使用 $ 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
(参见 Built-in Variables That Convey Information 部分)。如果使用常规字段拆分,则值为 PROCINFO["FS"]
,如果使用固定宽度字段拆分,则值为 "FS"
,如果使用基于内容的字段拆分,则值为 "FIELDWIDTHS"
。
同样在 Changing FS Does Not Affect the Fields 中,它们描述了更改如何影响下一条记录:
<块引用>根据 POSIX 标准,awk 的行为应该就像每条记录在读取时被拆分为字段一样。特别是,这意味着如果您在读取记录后更改 "FPAT"
的值,字段的值(即它们如何拆分)应反映 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
显示当前记录 (FS) 中设置的信息,而不是 Awk 在处理数据时考虑的信息(即 FPAT)。如果我们交换分配,也会发生同样的情况:
PROCINFO["FS"]
为什么 $ gawk 'BEGIN{FS=";"}{FPAT="..."; print PROCINFO["FS"]; print $1}' <<< "hello;you"
FPAT
hello
显示的 FS 与打印它的记录中使用的 FS 不同?
答案 0 :(得分: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=";"
$1
已经基于 FPAT="..."
填充,然后打印 PROCINFO["FS"]
新值(这将是使用下次将记录拆分为多个字段),然后打印在设置 $1
之前填充的 FS=";"
值。
如果您将 $0
设置为自身,字段拆分将再次发生,这次使用新的 FS 值而不是原始 FPAT 值:
$ gawk 'BEGIN{FPAT="..."}{FS=";"; print PROCINFO["FS"]; print $1; $0=$0; print $1}' <<< "hello;you"
FS
hel
hello