管道awk通过排序没有正确排序

时间:2015-12-04 10:02:54

标签: linux bash sorting awk

假设有一个listing.dat文件(位于:http://pastebin.com/gWkJS2fH

以下语句将为一个城市提供支持,将其传递给awk,它将查找任何选项卡并分隔成列。然后我将数据传输到sort,它不会按升序对任何列进行排序。

我知道原因是由于标签,但我无法弄清楚为什么或如何解决它。

egrep Toronto listing1.dat | gawk -F "[\t]+" '($3 >= 2) && ($4 >= 500) && ($5 <= 900000) && ($6 <= 5)' | sort -nk5

这应按价格按升序排序结果。

任何想法我能做什么?

5 个答案:

答案 0 :(得分:2)

AWK doesn't work in Bash Script中所述,首先摆脱不需要的grep。你的排序可能需要“-b”,意思是忽略领先的空白; man page here:http://ss64.com/bash/sort.html

答案 1 :(得分:2)

awk '$(NF-3)>=2&&$(NF-2)>=500&&$(NF-1)<=900000&&$NF <=5{++j;a[j]=$0;b[j]=$(NF-1)}END{asort(b,c);for(i in c){for(k in b)if(b[k]==c[i]){print a[k];delete b[k]}}}' file
450 West 33rd Street            Toronto         2       890     400000          1
11777 Mississippi Avenue        Toronto         2       890     400000          2
266 King Street West            Toronto         2       840     450000          1
4802 Fifth Avenue               Mississauga     3       1100    450000          5
4500 Wilshire Blvd              Vaughn          3       1420    500000          4
555 Broadway                    Toronto         2       840     500000          4
2213 Mt. Vernon Avenue          Vaughn          2       890     500000          4
1145 17th Street                Toronto         2       790     500000          3
100 Universal City Plaza        Toronto         2       890     580000          1
122 Sherbourne Street           Vaughn          2       690     650000          4
401 Mercer Street               Markham         2       890     700000          4
1416 North LaBrea Avenue        Markham         4       1890    880000          4
One Lincoln Plaza               Toronto         2       980     900000          1

答案 2 :(得分:2)

这里的问题是gawk没有改变线路;地址和城市有时会被多个标签分隔。

您想要的是将输出字段分隔符设置为单个选项卡。现在排序将找到正确的列。我就是这样写的:

gawk '
        BEGIN{FS="\t+"
        OFS="\t"}
    /Toronto/ && \
    $3 >= 2 && \
    $4 >= 500 && \
    $5 <= 900000 && \
    $6 <= 5 && \
    $1=$1' data | sort -nt$'\t' -k5

编辑了一些评论:

  • 在BEGIN块
  • 中设置字段分隔符和输出字段分隔符
  • 在条件列表中将城市名称设置为匹配器
  • $1=$1添加到条件中。这样可以“重新计算”该行,因此输入字段分隔符将替换为输出字段分隔符。
  • 需要一些技巧让sort听取tab作为分隔符。 $'\t'可能不适用于所有炮弹,但应该是合理的标准。

编辑2以删除条件中不必要的()

答案 3 :(得分:2)

如果您按照我关于发布样本输入/输出的建议,只是为了向您展示我说的时候我会有更好的答案,这里有一个例子:

$ cat tst.awk
BEGIN { FS="\t+" }
($2=="Toronto") && ($3>=2) && ($4>=500) && ($5<=900000) && ($6<=5) {
    hits[$5][$0]
}
END {
    PROCINFO["sorted_in"] = "@ind_num_asc"
    for (i in hits) {
        for (j in hits[i]) {
            print j
        }
    }
}

$ awk -f tst.awk file
450 West 33rd Street            Toronto         2       890     400000          1
11777 Mississippi Avenue        Toronto         2       890     400000          2
266 King Street West            Toronto         2       840     450000          1
555 Broadway                    Toronto         2       840     500000          4
1145 17th Street                Toronto         2       790     500000          3
100 Universal City Plaza        Toronto         2       890     580000          1
One Lincoln Plaza               Toronto         2       980     900000          1

请注意,格式化已保留,您不需要任何外部工具,如grep或sort,也不需要管道。它还可以防止出现在错误环境中的单词Toronto,例如当地址为27 Toronto Ave, London时,或者当您要搜索27 London Ave, New YorkYork时,请尝试接受的答案。

以上使用GNU awk 4. *代表sorted_in

答案 4 :(得分:1)

egrep Toronto listing1.dat | gawk -F "\t+" '{if (($3 >= 2) && ($4 >= 500) && ($5 <= 900000) && ($6 <= 5)) {printf $5 "\t"; print}}' | sort -nk1 | cut -f 2-

这做了一些事情:

1)它将第5个字段的副本添加到行的开头,然后是单个选项卡。

2)排序现在很简单,因为您只需要根据单标签分隔对第一列进行排序。这会在行的其余部分保留可变数量的选项卡,使其看起来很好并且对齐(如果需要)。

3)只需使用cut保留第二个字段以后的所有内容(即删除前面的第一列)