如何在 awk 中获取数组的长度?

Posted

技术标签:

【中文标题】如何在 awk 中获取数组的长度?【英文标题】:How can I get the length of an array in awk? 【发布时间】:2012-03-10 05:58:28 【问题描述】:

这个命令

echo "hello world" | awk 'split($0, array, " ") ENDprint length(array) '

对我不起作用并给出此错误消息

awk:第 1 行:对数组数组的非法引用

为什么?

【问题讨论】:

实际上,您的代码对我有用,并按预期返回 2。 它适用于gawk,但不适用于POSIX awkgawk --posix 【参考方案1】:

拆分数组时,返回元素个数,所以可以这样说:

echo "hello world" | awk 'n=split($0, array, " ") ENDprint n '
# ------------------------^^^--------------------------------^^

输出是:

2

【讨论】:

我之前用过 split() ,但从来没有意识到它返回了一个值! @bgStack15 惊喜! .. 是的,多么方便的价值。另外,我认为您会发现 awk 中的大多数函数都返回一些值,可能是基于 c 语言 0 的错误或一些非零值作为有用信息返回的。祝你好运!【参考方案2】:

先生。 Ventimiglia 的功能需要稍作调整才能完成工作(参见 for 语句中的分号):

function alen(a, i) 
    for(i in a);
    return i

但不要在所有情况或时间都工作。这是因为 awk 存储和“查看”数组索引的方式:它们是关联的,不一定是连续的(如 C)。因此,i 不会返回“最后一个”元素。

要解决它,你需要计算:

function alen(a, i, k) 
    k = 0
    for(i in a) k++
    return k

并且,以这种方式,请注意“一维”数组的其他索引类型,其中索引可能是字符串。请参阅:http://docstore.mik.ua/orelly/unix/sedawk/ch08_04.htm。对于“多维”和任意数组,请参阅http://www.gnu.org/software/gawk/manual/html_node/Walking-Arrays.html#Walking-Arrays。

【讨论】:

【参考方案3】:

我不认为这个人在问,“我如何拆分字符串并获得结果数组的长度?”我认为他们提供的命令只是它出现的情况的一个例子。特别是,我认为该人在问 1)为什么 length(array) 会引发错误,以及 2)如何在 awk 中获取数组的长度?

第一个问题的答案是长度函数在 POSIX 标准 awk 中不能对数组进行操作,尽管它在 GNU awk (gawk) 和其他一些变体中可以。第二个问题的答案是(如果我们想要一个适用于所有 awk 变体的解决方案)进行线性扫描。

例如这样的函数:

function alen (a,     i) 
    for (i in a);
    return i;

注意:第二个参数 i 需要解释一下。

在 awk 中引入局部变量的方式是作为额外的函数参数,约定是通过在这些参数之前添加额外的空格来表示这一点。这在 GNU Awk 手册 here 中进行了讨论。

【讨论】:

优点。我的目标是使用 O.P. 的术语来回答原始问题,即。 awk 'split($0, array, " ")...',因此是我的答案,取自原始“The Awk 编程语言”中 split 的使用。祝大家好运。 谢谢。没想到我的回答这么精辟。我有点着急。也许我会软化一点。 但这只是返回数组的第一个索引?此外,POSIX 未指定数组迭代的顺序。 第二个问题的答案是(如果我们想要一个适用于所有 awk 变体的解决方案) [is] 进行线性扫描 AND 计算并返回给定数组中元素的数量:... for(i in a) c++; return c 哦,不是真的。这个答案的修订版 4 或 6 并没有真正返回数组的长度,而只是返回它的随机最后一个索引。【参考方案4】:

只想指出:

不需要为了打印而存储split 函数的结果。 如果没有为拆分提供分隔符,则将使用默认的FS(空格)。

END 部分在这里无用

echo 'hello world' | awk 'print split($0, a)'

【讨论】:

【参考方案5】:

gawk你可以使用函数length()

$ gawk 'BEGINa[1]=1; a[2]=2; a[23]=45; print length(a)'
3

$ gawk 'BEGINa[1]=1; a[2]=2; print length(a); a[23]=45; print length(a)'
2
3

来自The GNU Awk user's guide:

对于 gawk 和其他几个 awk 实现,当给定一个数组参数时,length() 函数返回数组中元素的数量 数组。 (c.e.)这并不像一开始看起来那么有用,因为 不保证数组从一索引到 其中的元素。如果在命令行上提供了 --lint(请参阅 选项),gawk 警告说传递数组参数是不可移植的。 如果提供了 --posix,则使用数组参数是一个致命错误(请参阅 数组)。

【讨论】:

我认为大多数流行的awk都支持这个功能,不仅仅是gawk。我在 macOS 和 NetBSD 上尝试了 awk,两者都可以工作。【参考方案6】:

MacOSX Lion 上的示例以显示使用的端口(输出可以是 192.168.111.130.49704 或 ::1.49704):

   netstat -a -n -p tcp | awk '/\.[0-9]+ / n=split($4,a,"."); print a[n]'

在此示例中,打印第 4 列的最后一个数组项:“49704”

【讨论】:

【参考方案7】:

如果你不使用 gawk,试试这个。

awk 'BEGINtest="aaa bbb ccc";a=split(test, ff, " "); print ff[1]; print a; print ff[a]'

输出:

aaa
3
ccc

8.4.4 使用 split() 创建数组http://docstore.mik.ua/orelly/unix/sedawk/ch08_04.htm

【讨论】:

【参考方案8】:

这是我获取数组长度的一种快速方法,如果不存在则初始化为零长度,但不要覆盖任何现有的或意外添加额外的元素:

(g/mawk) 'function arrayinit(ar, x)  for(x in ar) break; return length(ar) ;

for 循环基本上是 O(1),因为它在任何现有元素上退出,无论排序顺序如何。我以前的方法是测试或拆分空字符串。这种方式节省了拆分步骤,因为 for 循环可能是隐式的。

这也适用于像 arr[x,y] 或 gawk arr[x][y] 这样的伪多维数组,而不必担心“x”是否是 gawk 意义上的子数组。

【讨论】:

【参考方案9】:
echo "hello world" | awk 'lng=split($0, array, " ") ENDprint lng) '

【讨论】:

以上是关于如何在 awk 中获取数组的长度?的主要内容,如果未能解决你的问题,请参考以下文章

如何将数组的值作为第二个参数传递给 awk 的 split 函数?

awk 如何获取每行最后一个字符

在java中,一个数组的长度不固定(长度大于1),如何获取数组的最后一个元素

如何在c中获取数组的长度[重复]

Java中如何获取多维数组的长度

如何在 Angular 中获取过滤后的 ngRepeat 数组的长度?