为什么awk中的split(字符串,正则表达式)使用第一个位置的最后一个字段



quick awkscript 如下:

awk ' BEGIN{
split("AnBnCnD", fooarray)
i=0
for (i in fooarray) print fooarray[i] 
} '

输出:

D
A
B
C

我觉得我错过了一些主要细节,但是 D no 如何排在最后?如在

A
B
C
D

D 位于最后一个位置,您只是没有按其索引的连续数字顺序访问数组。看:

awk 'BEGIN{
split("AnBnCnD", fooarray)
for (i in fooarray) print fooarray[i]
print "-------"
for (i=1; i in fooarray; i++) print fooarray[i]
}'
D
A
B
C
-------
A
B
C
D

我觉得这个话题引起了很多困惑,所以让我们看看我是否可以澄清一下:

awk 数组的 2 个基本品质是:

  1. 所有数组索引都是字符串,即使是那些看起来是数字的,并且
  2. 为了提高效率,数组存储为哈希表。

因此,假设您有一个类似于 "A B C" 的字符串,您想要调用split()以存储在数组中。当你这样做split("A B C", arr)你会在内存中得到这样的东西:

 arr[  "3:C"   "1:A"    "2:B"   ]

即,值 A、B 和 C 被散列到一些内存位置,并与指示它们在原始字符串中出现的顺序的索引值一起存储在那里。哈希算法可以按任何顺序将它们放入内存中。谷歌"哈希表"。所以数组实际上存储为这个哈希表:

arr content @ address 1 = "index=3, value=C"
arr content @ address 2 = "index=1, value=A"
arr content @ address 3 = "index=2, value=B"

提高效率的in运算符(否则为什么要打扰哈希表)只是按照数组元素在内存中的存储顺序访问它们,所以当你这样做时

for (i in arr)

您可以按照arr在哈希表中的存储顺序获取访问的内容:

address=1 => i = 3, arr[i] = C
++address => i = 1, arr[i] = A
++address => i = 2, arr[i] = B
i设置为 3 然后设置为

1 然后 2,因此 arr[i] 的值为 C 然后 A 然后 B.请注意遍历 arr 内容的简单、高效的算术++address

另一方面,如果您写:

for (i=1; i in arr; i++)

然后awk将i设置为1,然后必须对数组进行哈希查找以搜索具有索引1的元素并打印该元素,以便得到:

i=1
search arr for address containing index i=1
=> address = 2, i = 1, arr[1] = A
++i
search arr for address containing index i=2
=> address = 3, i = 2, arr[2] = B
++i
search arr for address containing index i=3
=> address = 1, i = 3, arr[3] = C

看到效率差异了吗?现在,我们不再只是简单地以增量方式遍历内存地址,而是对每个所需的索引进行哈希查找。

当您在条件上下文中编写i in arr时,例如 if (i in arr)for (i=1; i in arr; i++)而不是循环范围上下文for (i in arr)那么你要求awk做的只是i的哈希查找,以查看它是否存在于数组中:

search arr for address containing index i
return 1 if found, 0 otherwise.

如果您有一个使用字符串索引手动填充的数组,例如:

arr["First"] = "Bill"
arr["Last"]  = "Smith"
arr["Title"] = "Mr."

让我们假设哈希算法根据其值的长度创建数组内容,然后你会得到:

arr[   "Title:Mr."   "First:Bill"    "Last:Smith"    ]

上面描述的所有内容都将以完全相同的方式工作,因此第一个示例使用看起来很数值的索引 1、2 和 3 这一事实与 awk 中的数组的工作方式完全无关 - 所有索引都是字符串,数组内容存储为 index + value 对的哈希表。

在 GNU awk 中,您可以更改 in 运算符的行为,以根据各种条件查找数组内容,而不是简单地通过填充PROCINFO["sorted_in"]按顺序遍历地址 - 例如,您可以将其设置为特定的预定义字符串,以告诉in根据索引的数字或字符串顺序查找数组内容, 升序或降序,或各种其他条件,您可以编写自己的函数来控制顺序。如果您需要特定的数组遍历顺序,这对于提高代码的简洁性非常有用,但如果您使用它并且不需要它,显然会降低性能。有关详细信息,请参阅 http://www.gnu.org/software/gawk/manual/gawk.html#Controlling-Array-Traversal。

希望这有助于解释awk阵列存储和in运算符的工作方式。如果没有 - 很抱歉增加了混乱!

awk 不保证您在使用 in 时遍历数组的顺序。

如果要

确保顺序,您可以手动遍历数组(使用来自split)的返回值以数字方式)。

或者,对于awk 4+的版本(我相信),您可以将PROCINFO["sorted_in"]设置为适当的值。有关详细信息,请参阅 GNU Awk 用户指南。

相关内容

最新更新