【问题标题】:How to use AWK to print associative array in a loop correctly?如何使用 AWK 在循环中正确打印关联数组?
【发布时间】:2019-01-11 22:05:01
【问题描述】:
Beth    45  0
Danny   33  0
Thomas  22  40  
Mark    65  100 
Mary    29  121 
Susie   39  76.5
Joey    51  189.52
Peter   23  78.26
Maximus 34  289.71
Rebecca 21  45.79
Sophie  26  28.44
Barbara 24  107.36
Elizabeth   35  105.69
Peach   40  102.69
Lily    41  123 

以上是一个数据文件,包含三个字段:姓名、年龄、工资。

我想打印 30 岁以上和 30 岁以下人员的平均工资、人数和姓名。

在这个练习中,我想练习使用字符串作为下标。

这是我的 AWK 代码:

BEGIN { OFS = "\t\t" }   
{
    if ($2 < 30) 
    {   
        a = "age below 30";
        salary[a] += $NF; 
        count[a]++;
        name[a] = name[a] $1 "\t";
    }   
    else
    {   
        a = "age equals or above 30";
        salary[a] += $NF; 
        count[a]++;
        name[a] = name[a] $1 "\t";
    }   
}

END {
    for (a in salary)
        for (a in count)
            for (a in name)
            {
                print "The average salary of " a " is " salary[a] / count[a];
                print "There are " count[a] " people "  a ; 
                print "Their names are " name[a];
                print "********************************************************";
            }
}

以下是输出:

The average salary of age equals or above 30 is 109.679
There are 9 people age equals or above 30
Their names are Beth    Danny   Mark    Susie   Joey    Maximus Elizabeth   Peach   Lily    
********************************************************
The average salary of age below 30 is 70.1417
There are 6 people age below 30
Their names are Thomas  Mary    Peter   Rebecca Barbara Sophie  
********************************************************
The average salary of age equals or above 30 is 109.679
There are 9 people age equals or above 30
Their names are Beth    Danny   Mark    Susie   Joey    Maximus Elizabeth   Peach   Lily    
********************************************************
The average salary of age below 30 is 70.1417
There are 6 people age below 30
Their names are Thomas  Mary    Peter   Rebecca Barbara Sophie  
********************************************************
The average salary of age equals or above 30 is 109.679
There are 9 people age equals or above 30
Their names are Beth    Danny   Mark    Susie   Joey    Maximus Elizabeth   Peach   Lily    
********************************************************
The average salary of age below 30 is 70.1417
There are 6 people age below 30
Their names are Thomas  Mary    Peter   Rebecca Barbara Sophie  
********************************************************
The average salary of age equals or above 30 is 109.679
There are 9 people age equals or above 30
Their names are Beth    Danny   Mark    Susie   Joey    Maximus Elizabeth   Peach   Lily    
********************************************************
The average salary of age below 30 is 70.1417
There are 6 people age below 30
Their names are Thomas  Mary    Peter   Rebecca Barbara Sophie  
********************************************************

输出对我来说很难理解。

我的预期应该是这样的:

The average salary of age equals or above 30 is 109.679
There are 9 people age equals or above 30
Their names are Beth    Danny   Mark    Susie   Joey    Maximus Elizabeth   Peach   Lily    
********************************************************
The average salary of age equals or above 30 is 109.679
There are 9 people age equals or above 30
Their names are Thomas  Mary    Peter   Rebecca Barbara Sophie  
********************************************************
The average salary of age equals or above 30 is 109.679
There are 6 people age below 30
Their names are Beth    Danny   Mark    Susie   Joey    Maximus Elizabeth   Peach   Lily    
********************************************************
The average salary of age equals or above 30 is 109.679
There are 6 people age below 30
Their names are Thomas  Mary    Peter   Rebecca Barbara Sophie  
********************************************************
The average salary of age below 30 is 70.1417
There are 9 people age equals or above 30
Their names are Beth    Danny   Mark    Susie   Joey    Maximus Elizabeth   Peach   Lily    
********************************************************
The average salary of age below 30 is 70.1417
There are 9 people age equals or above 30
Their names are Thomas  Mary    Peter   Rebecca Barbara Sophie  
********************************************************
The average salary of age below 30 is 70.1417
There are 6 people age below 30
Their names are Beth    Danny   Mark    Susie   Joey    Maximus Elizabeth   Peach   Lily    
********************************************************
The average salary of age below 30 is 70.1417
There are 6 people age below 30
Their names are Thomas  Mary    Peter   Rebecca Barbara Sophie  
********************************************************

所以我的第一个问题是:我哪里理解错了?

我的第二个问题是: 我实际上不需要这么多循环。我只需要

The average salary of age equals or above 30 is 109.679
There are 9 people age equals or above 30
Their names are Beth    Danny   Mark    Susie   Joey    Maximus Elizabeth   Peach   Lily    
********************************************************
The average salary of age equals or above 30 is 109.679
There are 9 people age equals or above 30
Their names are Thomas  Mary    Peter   Rebecca Barbara Sophie  
********************************************************

for (a in salary, count, names) 不起作用。有没有更好的办法?

【问题讨论】:

  • 如果你删除for (a in salary) for (a in count)会发生什么?
  • 谢谢,它有效。我还找到了 for (a in sale) for (a in count) for (a in name) ,这三个 for() 中的任何一个都可以解决问题。对我来说还是有点奇怪

标签: arrays string awk substring


【解决方案1】:
for (x in salary)
    for (y in count)
        for (z in name)
            print "foo"

for every index in salary, loop through every index in count and while doing so, for every index in count loop through every index in name and print "foo" each time。因此,如果薪水、计数和姓名各有 3 个条目,那么您将打印 "foo" 3*3*3 = 9 次。

它比你的代码更复杂,因为你使用相同的变量来保存嵌套循环的每一层的每个数组的索引值:

for (a in salary)
    for (a in count)
        for (a in name)

所以我不确定 awk 会对此做什么 - 它甚至可能是未定义的行为。

由于所有 3 个数组都有相同的索引,只需选择其中一个数组并循环它的索引,然后您就可以使用相同的索引访问所有 3 个数组。

$ cat tst.awk
{
    bracket = "age " ($2 < 30 ? "under" : "equals or above") " 30"

    names[bracket] = (bracket in names ? names[bracket] "\t" : "") $1
    count[bracket]++
    salary[bracket] += $NF
}
END {
    for (bracket in names) {
        print "The average salary of", bracket, "is", salary[bracket] / count[bracket]
        print "There are", count[bracket], "people",  bracket
        print "Their names are", names[bracket]
        print "********************************************************"
    }
}

$ awk -f tst.awk file
The average salary of age equals or above 30 is 109.679
There are 9 people age equals or above 30
Their names are Beth    Danny   Mark    Susie   Joey    Maximus Elizabeth       Peach   Lily
********************************************************
The average salary of age under 30 is 70.1417
There are 6 people age under 30
Their names are Thomas  Mary    Peter   Rebecca Sophie  Barbara
********************************************************

【讨论】:

    猜你喜欢
    • 2014-02-16
    • 2015-08-23
    • 2023-03-12
    • 1970-01-01
    • 2015-04-03
    • 1970-01-01
    • 1970-01-01
    • 2020-04-21
    • 2017-10-07
    相关资源
    最近更新 更多