【问题标题】:awk: Selecting rows based on the first 3 different values of a given columnawk:根据给定列的前 3 个不同值选择行
【发布时间】:2016-03-16 03:45:20
【问题描述】:

我想读取 fileIn.txt(逗号分隔)并输出 fileOut.txt,其中仅包含与给定列的前 3 个不同值匹配的行。例如,我的输入文件如下所示:

fileIn.txt
#location,day,time
home,mon,01:00
office,mon,06:00
home,mon,10:00
office,tues,03:00
home,wed,08:00
home,wed,11:00
home,thurs,02:00
home,fri,01:00
diner,fri,07:00
party,fri,09:00
home,sat,02:00
mall,sat,06:00
home,sat,09:00
beach,sun,01:00

我只想选择前 3 天不同的行,以便我的输出文件如下所示:

fileOut.txt
#location,day,time
home,mon,01:00
office,mon,06:00
home,mon,10:00
office,tues,03:00
home,wed,08:00
home,wed,11:00

【问题讨论】:

  • 可以假设输入文件已经排序了吗?
  • 是的,你可以假设。

标签: linux unix awk gawk


【解决方案1】:

您的问题有点令人困惑。但是,如果我理解正确,您想打印出与脚本在文件中找到的前 3 个不同值中的任何一个匹配的一周中某一天的任何行。你可以像这样用 awk 做到这一点

BEGIN { FS="," }

{
    if(dayCount < 3 && !($2 in days)) { days[$2] = 1; ++dayCount }
    if ($2 in days) { print }
}

【讨论】:

    【解决方案2】:

    awk 来救援! 以更惯用的形式包括标题。

    $ awk -F, 'NR==1{c[$2]} length(c)<4{c[$2]} $2 in c' file
    
    #location,day,time
    home,mon,01:00
    office,mon,06:00
    home,mon,10:00
    office,tues,03:00
    home,wed,08:00
    home,wed,11:00
    

    解释:第一个块用第一行值初始化数组,因为在初始化之前无法检查数组的长度。数组 c 包含不同的 $2 字段,我们不断添加直到第二个块中的大小达到 4(即,带有标题将有 4 个不同的值)。在最后一个块中,检查该行是否是不同的值之一并打印(作为默认操作)。

    我不想让它更神秘,但你可以合并前两个块,因为动作是相同的

    $ awk -F, 'NR==1 || length(c)<4 {c[$2]} $2 in c' file
    

    在为NR==1 初始化之前不评估长度取决于短路的逻辑操作。

    【讨论】:

    • 你这个巫师......你能为我们这些新手破译吗?
    • 哇,是的,请。 . .
    【解决方案3】:
    awk -F, '
        /^#/            {print; next}   # keep comments
        ++seen[$2] == 1 {count++}       # incr counter the first time value is seen
        count > 3       {exit}          # quit if we have seen 4 values
                        {print}         # otherwise print this line
    ' file
    

    【讨论】:

      猜你喜欢
      • 2012-11-02
      • 2016-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-24
      相关资源
      最近更新 更多