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

这个命令

echo "hello world" | awk '{split($0, array, " ")} END{print length(array) }'

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

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

为什么?

【问题讨论】:

  • 实际上,您的代码对我有用,并按预期返回 2。
  • 它适用于gawk,但不适用于POSIX awkgawk --posix

标签: awk


【解决方案1】:

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

echo "hello world" | awk '{n=split($0, array, " ")} END{print 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 'BEGIN{a[1]=1; a[2]=2; a[23]=45; print length(a)}'
      3
      
      $ gawk 'BEGIN{a[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 'BEGIN{test="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, " ")} END{print lng) }'
            

            【讨论】:

              猜你喜欢
              • 2017-06-19
              • 1970-01-01
              • 2022-09-23
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-06-22
              相关资源
              最近更新 更多