【问题标题】:Confused on how AWK processes commands对 AWK 如何处理命令感到困惑
【发布时间】:2021-02-04 22:08:44
【问题描述】:

因此,对于这个问题,我将给出两个示例代码块,但略有不同。样本 1 给出正确结果,样本 2 给出错误结果。 此处的正确结果意味着它应该能够读取应该从 csv 文件读取的字段,并仅打印这些字段中存在的字符串的计数。示例代码后的示例如下所示。 请注意,该程序会跳过 CSV 文件中的标题行。

示例 1:

#!/bin/awk -f

BEGIN {
    FIELDS_LIST = ARGV[1];
    delete ARGV[1];
    FS = ", *"

    num = split(FIELDS_LIST,arr,",")
    for(i in arr)
        fields[arr[i]]
}

{
    for(i = 1; i <= NF; i++)
    {
        if(FNR != 1)
          if(i in fields)
            data[++data_index] = $i
    }

}

END {
    produce_numbers(data)

    PROCINFO["sorted_in"] = "@val_num_desc"

    for(i in freq)
        printf "%s\t%d\n", i, freq[i]
}

function produce_numbers(sortedarray)
{
    n = asort(sortedarray)

    for(i = 1 ; i <= n; i++)
    {
        freq[sortedarray[i]]++
    }
    return
}

示例 2:

#!/bin/awk -f

BEGIN {
    FIELDS_LIST = ARGV[1];
    delete ARGV[1];
    FS = ", *"

    num = split(FIELDS_LIST,arr,",")
    for(i in arr)
        fields[arr[i]]
}

{
    for(i = 1; i <= NF; i++)
    {
        if(FNR != 1)
          if(i in arr)                 #This is the only line changed, fields was changed to arr
            data[++data_index] = $i
    }

}

END {
    produce_numbers(data)

    PROCINFO["sorted_in"] = "@val_num_desc"

    for(i in freq)
        printf "%s\t%d\n", i, freq[i]
}

function produce_numbers(sortedarray)
{
    n = asort(sortedarray)

    for(i = 1 ; i <= n; i++)
    {
        freq[sortedarray[i]]++
    }
    return
}

代码将使用 ./example-awk.awk 2,3 simple.csv 之类的东西调用,其中包含 simple.csv

Field1,Field2,Field3,Field4
A,V,A,C
B,C,V,D
E,W,C,A

结果应该是

V    2
C    2
A    1
W    1

样本 1 提供了正确的结果,但是样本 2 提供了

A    1
B    1
C    1
E    1
W    1
V    1

显示它仅从字段 1 和 2 读取,而不是从命令行参数指定的 2 和 3。 我想知道为什么在 begin 中创建第二个数组,然后使用它而不是原来的 arr 来解决问题。

【问题讨论】:

  • 为什么不打印字段中而不是 arr 中的 i?

标签: bash csv awk


【解决方案1】:
if (i in arr)

测试i 是否是arr 数组中的键。但是你想要的字段编号是数组中的值,而不是索引。

您可以遍历arr 并获取这些字段,而不是遍历所有字段并对其进行测试。

此外,您应该在执行该行的任何代码之前测试FNR != 1,以跳过标题,而不是每次循环。

#!/bin/awk -f

BEGIN {
    FIELDS_LIST = ARGV[1];
    delete ARGV[1];
    FS = ", *"

    num = split(FIELDS_LIST,arr,",")
    for(i in arr)
        fields[arr[i]]
}

FNR != 1 {
    for (i in fields)
        data[++data_index] = $i
}

END {
    produce_numbers(data)

    PROCINFO["sorted_in"] = "@val_num_desc"

    for(i in freq)
        printf "%s\t%d\n", i, freq[i]
}

function produce_numbers(sortedarray)
{
    n = asort(sortedarray)

    for(i = 1 ; i <= n; i++)
    {
        freq[sortedarray[i]]++
    }
    return
}

【讨论】:

  • 您能解释一下究竟什么是键吗?我对 AWK 不够熟悉,无法完全理解。
  • 分配数组元素时,fields[x] = yx 是键,y 是值。
  • 就像传统数组中的数组索引。
  • 我明白了,这是有道理的。感谢您的宝贵时间!
猜你喜欢
  • 2021-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多