【问题标题】:Sorting Awk array by last name按姓氏对 awk 数组进行排序
【发布时间】:2015-05-25 02:10:52
【问题描述】:

在我的脚本中,我从一个活动贡献者文件开始,任何捐赠 500 美元的人都有资格参加比赛。任何符合该标准的人,我都会将其添加到具有递增索引的数组中,以根据需要调整大小。每个索引的格式如下所述,其中 X 是电话号码。在脚本的 END 部分,我需要按姓氏 ($2) 对这个数组进行排序以进行打印。我做了一些搜索,但空手而归。我不是要求有人为我键入脚本,只是为了给我指明更好的搜索方向或提供建议。我需要帮助对数组参赛者进行排序,因为目前它将按照我在作业中需要它们的方式正确填充字符串值。

其中 v1、2 和 3 是竞选贡献,我在命令中使用 -F'[ :]' 来获取空格和冒号作为字段分隔符。

输入文件lab4.data

Fname Lname:Phone__Number:v1:v2:v3   
Mike Harrington:(510) 548-1278:250:100:175 
Christian Dobbins:(408) 538-2358:155:90:201 
Susan Dalsass:(206) 654-6279:250:60:50 
Archie McNichol:(206) 548-1348:250:100:175 
Jody Savage:(206) 548-1278:15:188:150 
Guy Quigley:(916) 343-6410:250:100:175 
Dan Savage:(406) 298-7744:450:300:275 
Nancy McNeil:(206) 548-1278:250:80:75 
John Goldenrod:(916) 348-4278:250:100:175 
Chet Main:(510) 548-5258:50:95:135   
Tom Savage:(408) 926-3456:250:168:200  
Elizabeth Stachelin:(916) 440-1763:175:75:300 

存储任何 > $500 的数组,创建 $8 并保存值 $5+$6+$7: 数组被初始化并填充到下面给出的for循环中

$8 = $5+$6+$7;

contestants[len++]

循环检查将人员添加到参赛者数组。 name 和 number 是保存各自值以供以后使用的数组。

for(i=0;i<=NR;i++)if(contrib[i]>500){contestants[len++]= name[i]"   "number[i] }

索引的格式(参赛者[len++]所需的数组值):

[0]   Mike Harrington (510) 548-1278
[1]   Archie McNichol (206) 548-1348 
[2]   Guy Quigley (916) 343-6410
[3]   Dan Savage (406) 298-7744
[4]   John Goldenrod (916) 348-4278
[5]   Tom Savage (408) 926-3456
[6]   Elizabeth Stachelin (916) 440-1763

循环打印/检查数组是否被正确填充(它是)

for (i=0; i <len; i++) {print contestants[i]}

输出:

Mike Harrington (510) 548-1278
Archie McNichol (206) 548-1348
Guy Quigley (916) 343-6410
Dan Savage (406) 298-7744
John Goldenrod (916) 348-4278
Tom Savage (408) 926-3456
Elizabeth Stachelin (916) 440-1763

所需的最终输出:忽略格式,因为它在我的终端中正确显示我很难在这里得到一切都很好。

               ***FIRST QUARTERLY REPORT***                          
            ***CAMPAIGN 2004 CONTRIBUTIONS***                       

   Name            Phone             Jan  |  Feb  |  Mar  |  Total Donated 
Mike Harrington     (510)548-1278   $ 250   $ 100   $ 175   $ 525
Christian Dobbins   (408)538-2358   $ 155   $ 90    $ 201   $ 446
Susan Dalsass       (206)654-6279   $ 250   $ 60    $ 50    $ 360
Archie McNichol     (206)548-1348   $ 250   $ 100   $ 175   $ 525
Jody Savage         (206)548-1278   $ 15    $ 188   $ 150   $ 353
Guy Quigley         (916)343-6410   $ 250   $ 100   $ 175   $ 525
Dan Savage          (406)298-7744   $ 450   $ 300   $ 275   $ 1025
Nancy McNeil        (206)548-1278   $ 250   $ 80    $ 75    $ 405
John Goldenrod      (916)348-4278   $ 250   $ 100   $ 175   $ 525
Chet Main           (510)548-5258   $ 50    $ 95    $ 135   $ 280
Tom Savage          (408)926-3456   $ 250   $ 168   $ 200   $ 618
Elizabeth Stachelin (916)440-1763   $ 175   $ 75    $ 300   $ 550
-----------------------------------------------------------------------------
SUMMARY
-----------------------------------------------------------------------------
The campaign received a total of $6137.00 for this quarter.
The average donation for the 12 contributors was $511.42.
The highest total contribution was $1025.00 made by Dan Savage.
                ***Thank you Dan Savage***                           
The following people donated over $500 to the campaign.
They are eligible for the quarterly drawing!!
Listed are their names(sorted by last names) and phone numbers.

John Goldenrod (916) 348-4278
Mike Harrington (510) 548-1278
Archie McNichol (206) 548-1348
Guy Quigley (916) 343-6410
Dan Savage (406) 298-7744
Tom Savage (408) 926-3456
Elizabeth Stachelin (916) 440-1763

Thank you all for your continued support!!

【问题讨论】:

  • 您可能对awk.info/?Sorting感兴趣
  • 请阅读 Ed 和 Simon 的回答。 simon 的方法更简单,但 Ed 的方法更可行,并且使用了更先进的技术。

标签: arrays sorting awk


【解决方案1】:

使用gawk,可以直接使用内置排序功能,例如

BEGIN {
    data["Jane Doe (123) 456-7890"] = 600;
    data["Fred Adams (123) 456-7891"] = 800;
    data["John Smith (123) 456-7892"] = 900;
    exit;
    }

END {
    for (i in data) {
        split(i,x," ")
        data1[x[2] " " x[1] " " x[3] " " x[4]] = i;
        }
    asorti(data1,sdata1);
    for (i in sdata1) {
        print data1[sdata1[i]],"\t",data[data1[sdata1[i]]];
    }
}

... 产生:

Fred Adams (123) 456-7891        800
Jane Doe (123) 456-7890          600
John Smith (123) 456-7892        900

在普通的awk 中,可以通过将数组索引写入文件、对该文件进行排序然后使用getline 读回文件来实现相同的结果。

【讨论】:

  • 在这种情况下,我很高兴我提供了帮助,但没有帮助到损害您的学习体验。顺便说一句,我发现能够编写一个简短的自包含正确示例或SSCCE,就像您在答案中看到的那样,在我学习时对我有很大帮助。一旦我这样写了我的问题,我经常发现我可以自己回答。
  • @Ed Morton-我很感激这个帮助的人,但我还是新手。在做实验室的同时,我学到了很多东西。对于很多这一切,你所做的只是告诉我我做错了,西蒙的方法有效,当我们工作并得到答案时,我会按照你的要求取消选中它。您可以简单地说“xy & z 是加载数组的更好方式,而不是您正在执行的方式。我可以看到\告诉您显然,在这方面比我好得多,而且我不接受理所当然的建议。我正在再次调整我的问题,以包含我认为您可能需要的所有内容。
  • @Simon-我查看了 SSCCE,并将开始尝试在以后的问题中使用它
【解决方案2】:

解决此问题的方法是在读取数据时生成 pre-SUMMARY 输出,这样您就不需要将所有数据存储在数组中,只需将贡献超过 500 美元的人存储到数组中即可使用插入排序算法按所需顺序排列数组。

你会这样做:

awk -F':' '
NR==1 {
    print "header stuff"
    next
}
{
    tot = $3 + $4 + $5
    printf "%-20s%10s $%5s $%5s $%5s $%5s\n", $1, $2, $3, $4, $5, tot
}
tot > 500 {
    split($1,name,/ /)
    surname = name[2]
    numContribs++
    # insertion sort, check the algorithm:
    for (i=1; i<=numContribs; i++) {
        if (surname > surnames[i]) {
            for (j=numContribs; j>i; j--) {
                surnames[j+1] = surnames[j]
                contribs[j+1] = contribs[j]
            }
            surnames[i] = surname
            contribs[i] = $1 " " $2
            break
        }
    }
}
END {
    print "SUMMARY and text below it and then the list of $500+ contributors:"
    for (i=1; i<=numContribs; i++) {
        print contribs[i]
    }
}
' lab4.data

以上不是一个功能齐全的程序。它只是为了根据您的要求向您展示正确的方法。

【讨论】:

  • -所以我实现了初始化数组值的方法,尽管我必须在脚本中执行此操作,所以我只是使用语法,一切都很好。不过,我仍然无法对其进行排序,我会继续工作并重新检查。再次感谢 Ed
  • 我不明白您说“尽管我必须在脚本中执行此操作”时的意思,因为我发布的是脚本。请参阅en.wikipedia.org/wiki/Insertion_sort 或只是谷歌“插入排序”以了解执行此操作的算法,并参阅awk.info/?Sorting 了解在 awk 中实现各种其他排序算法。
  • -我收到了一封来自老师的电子邮件,他对文件使用想法的创造性感到惊讶。但他实际上与我一起研究如何简单地按照我的方式编写数组,并从他们不需要 a i 和 j 嵌套 for 循环进行排序。而且我可能措辞错误,但所有命令都需要在一个单独的文件中命令看起来像这样 awk -F'[ :]' a4b.script lab4.data,而不是 awk -F'[ :]' 'cmds here ' lab4.data 是你输入的,我相信它被称为原生 awk 脚本。 link
  • @Redeye 插入排序是最简单的排序算法,所以我无法想象你的老师想出什么更简单。而且您绝对 100% 不需要为此使用单独的文件,因为如果您想使用 UNIX 排序,您只需执行 print listOfNames | "sort"。不,如果它存储在文件中,则不称为“本机 awk 脚本”,它只是从文件执行脚本而不是从命令行执行脚本,请参阅gnu.org/software/gawk/manual/gawk.html#Invoking-Gawk。我很想知道你最终得到了什么 - 你介意编辑你的问题以包含它吗?
  • -我在玩游戏时使用了非常简单的版本。但我真的很喜欢你提出的更高级的主题,并且正在实验室中使用其中的一些。但我在我的 C++ 实验室工作,当我回到 shell 实验室时会更新​​。感谢大家的支持,我真的很需要它
猜你喜欢
  • 2013-11-03
  • 1970-01-01
  • 2020-11-03
  • 1970-01-01
  • 2015-07-08
  • 1970-01-01
  • 2021-01-04
  • 1970-01-01
  • 2019-05-06
相关资源
最近更新 更多