如何在 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 awk
或gawk --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 函数?