如何在awk中初始化数组数组?

时间:2012-12-28 02:19:23

标签: arrays awk initialization

是否可以在AWK中初始化这样的数组?

Colors[1] = ("Red", "Green", "Blue")
Colors[2] = ("Yellow", "Cyan", "Purple")

然后有一个二维数组,其中Colors [2,3] =“Purple”。


another thread我明白这是不可能的(“遗憾的是,没有办法在不滥用split()的情况下同时设置一个数组”)。无论如何,我想100%肯定,我确信还有其他人有同样的问题。

我正在寻找最简单的方法来初始化像上面那样的数组,将它编写得很好。

5 个答案:

答案 0 :(得分:12)

您可以轻松地创建二维数组。你不能做的,AFAIK,是在一次操作中初始化它。由于dmckee在注释中提示,无法初始化数组的原因之一是对下标的类型没有限制,因此不要求它们是纯数字。您可以在下面的脚本中执行多项任务。下标由变量SUBSEP指定的模糊字符正式分隔,默认值为034(U + 001C,FILE SEPARATOR)。显然,如果其中一个索引包含此字符,则会出现混淆(但是最后一次在字符串中使用该字符是什么时候?)。

BEGIN {
    Colours[1,1] = "Red"
    Colours[1,2] = "Green"
    Colours[1,3] = "Blue"
    Colours[2,1] = "Yellow"
    Colours[2,2] = "Cyan"
    Colours[2,3] = "Purple"
}
END {
    for (i = 1; i <= 2; i++)
        for (j = 1; j <= 3; j++)
            printf "Colours[%d,%d] = %s\n", i, j, Colours[i,j];
}

示例运行:

$ awk -f so14063783.awk /dev/null
Colours[1,1] = Red
Colours[1,2] = Green
Colours[1,3] = Blue
Colours[2,1] = Yellow
Colours[2,2] = Cyan
Colours[2,3] = Purple
$

答案 1 :(得分:12)

感谢您的回答。 无论如何,对于那些想要初始化一维数组的人来说,这是一个例子:

SColors = "Red_Green_Blue"
split(SColors, Colors, "_")
print Colors[1] " - " Colors[2] " - " Colors[3]

答案 2 :(得分:10)

如果您有GNU awk,则可以使用true multidimensional array。虽然这个答案使用split()函数,但它肯定不会滥用它。像:

一样运行
awk -f script.awk

script.awk的内容:

BEGIN {

    x=SUBSEP

    a="Red" x "Green" x "Blue"
    b="Yellow" x "Cyan" x "Purple"

    Colors[1][0] = ""
    Colors[2][0] = ""

    split(a, Colors[1], x)
    split(b, Colors[2], x)

    print Colors[2][3]
}

结果:

Purple

答案 3 :(得分:3)

现有的答案很有帮助,并且涵盖了所有方面,但我认为我会给出一个更有针对性的总结。

这个问题涉及两个方面:

  • 通常在Awk中初始化数组
  • 这样做是为了填补二维数组

数组初始化:

Awk有 没有数组文字(初始化)语法。

最简单的解决方法是:

  • 将数组元素表示为单字符串
  • 使用split()函数将该字符串拆分为数组元素。
$ awk 'BEGIN { n=split("Red Green Blue", arr); for (i=1;i<=n;++i) print arr[i] }'
Red
Green
Blue

这是OP在their own helpful answer中所做的。

如果元素本身包含空格,请使用不属于数据的自定义分隔符,在此示例中为|

$ awk 'BEGIN { n=split("Red (1)|Green (2)", arr, "|"); for (i=1;i<=n;++i) print arr[i] }'
Red (1)
Green (2)

二维数组的初始化:

  • 每个POSIX ,Awk有没有真正的多维数组,只有仿真 它使用一个 - 维数组,其索引与内置变量SUBSEP的值隐式连接,形成单键(索引;注意< em>所有 Awk数组都是 associative )。

    • arr[1, 2]实际上与arr[1 SUBSEP 2]相同,其中1 SUBSEP 2是构建键值的字符串连接
    • 因为没有真正的多维度 - 只有复数键的平面数组 - 您不能单独使用for (i in ...)枚举(伪)维度,例如获取主要的所有子索引(伪 - )仅维度1
    • SUBSEP的默认值是"INFORMATION SEPARATOR ONE" character,这是一个很少使用的控制字符,不太可能出现在日期中;在ASCII和UTF-8中,它表示为单字节0x1f;如果需要,您可以更改值。
  • 相比之下, GNU Awk ,作为非标准扩展, 支持真正的多维数组

    • 重要:您必须始终单独指定索引 ;例如,您必须使用arr[1,2]
    • 而不是arr[1][2]

POSIX兼容示例(类似于TrueY's helpful answer):

awk 'BEGIN {
  n=split("Red Green Blue", arrAux); for (i in arrAux) Colors[1,i] = arrAux[i]
  n=split("Yellow Cyan Purple", arrAux); for (i in arrAux) Colors[2,i] = arrAux[i]
  print Colors[1,2]
  print "---"
  # Enumerate all [2,*] values - see comments below.
  for (i in Colors) { if (index(i, 2 SUBSEP)==1) print Colors[i] }
}'
Green
---
Yellow
Cyan
Purple

请注意,使用复合键对具有一维数组的多维数组进行仿真具有以下不方便的含义

  • 需要辅助数组auxArr,因为您无法直接填充数组的给定(伪)维度。

  • 您无法使用for (i in ...)枚举一个(伪)维度,只能在(伪)维度上枚举所有索引

      上面的
    • for (i in Colors) { if (index(i, 2 SUBSEP)==1) print Colors[i] } 显示了如何通过枚举所有键然后只匹配其第一个组成索引为2的键来解决这个问题,这意味着键值必须从2开始,然后是SUBSEP

GNU Awk示例(类似于Steve's helpful answer,通过Ed Morton's评论进行了改进):

GNU Awk(非标准)对真正的多维数组的支持使得POSIX兼容解决方案的不便(大部分)消失
(但GNU Awk也没有数组初始值设定项):

gawk 'BEGIN {
  Colors[1][""]; split("Red Green Blue", Colors[1])
  Colors[2][""]; split("Yellow Cyan Purple", Colors[2])
  # NOTE: Always use *separate* indices: [1][2] instead of [1,2]
  print Colors[1][2]
  print "---"
  # Enumerate all [2][*] values
  for (i in Colors[2]) print Colors[2][i]
}'

注意:

  • 重要:如上所述,要解决多维数组中的特定元素,请始终使用单独的索引;例如,[1][2]而不是[1,2]

    • 如果您使用[1,2],您将获得标准的POSIX强制行为,并且您将错误地创建一个新的单个索引(键)与(字符串连接)值1 SUBSEP 2
  • split()可以方便地用于直接填充子数组。

  • 但作为先决条件,必须初始化二维目标数组:

    • Colors[1][""]Colors[2][""]就是这么做的。
    • 虚拟索引[""]就是在那里创建一个二维数组;当split()稍后填充该维度时,它将被丢弃。
  • 支持使用for (i in ...)枚举特定维度:

    • for (i in Colors[2]) ...只方便地枚举Colors[2]
    • 的子索引

答案 4 :(得分:2)

类似的解决方案。实际上并不需要SUBSEP=":",只需设置为demo的任何可见字符:

awk 'BEGIN{SUBSEP=":"
split("Red Green Blue",a); for(i in a) Colors[1,i]=a[i];
split("Yellow Cyan Purple",a); for(i in a) Colors[2,i]=a[i];
for(i in Colors) print i" => "Colors[i];}'

或者更隐蔽的版本:

awk 'BEGIN{SUBSEP=":"
split("Red Green Blue Yellow Cyan Purple",a); 
for(i in a) Colors[int((i-1)/3)+1,(i-1)%3+1]=a[i];
for(i in Colors) print i" => "Colors[i];}'

输出:

1:1 => Red
1:2 => Green
1:3 => Blue
2:1 => Yellow
2:2 => Cyan
2:3 => Purple