【问题标题】:AWK sort rows/lines numerically for blocks of numbersAWK 对数字块的行/行进行数字排序
【发布时间】:2016-09-12 13:53:12
【问题描述】:

我有一个文本文件:

aa 
80,143
60,312
50,123
20,14
bb
cc
80,163
60,132
50,23
20,48

我希望每次找到一个数字块时从最小数字到最大的行排序...

预期结果应如下所示:

aa 
20,14
50,123
60,312
80,143
bb
cc
20,48
50,23
60,132
80,163

如何调用排序函数来实现呢?

【问题讨论】:

  • 非常感谢您为我编辑表格!如何在文本框中完成并不是很明显......
  • 没问题。那么如果第一个数字是相同的两行会发生什么?
  • 想想您发布的输入。你知道有字母和数字排序,对吧?其中一个11 出现在2 之前,而另一个11 出现在2 之后?那么为什么要让您的示例输入数据使得每个前导数字都是相同的位数,所以如果我们使用了错误的排序方法,它看起来会起作用并且不会显示两行在逗号之前的部分相同的情况,所以您需要去逗号后面的数字来解析相对顺序? edit 你的问题至少包括 5,215,225,110 在一个块中。

标签: sorting awk


【解决方案1】:

也许最简单的方法是与awk 和朋友一起进行装饰/排序/取消装饰

$  awk '{if(!/[0-9,]/) {c++;d=0} else {d=1} print c "." d "," $0}' file |
   sort -nt, | 
   cut -d, -f2-

aa
20,14
50,123
60,312
80,143
bb
cc
20,48
50,23
60,132
80,163

【讨论】:

  • 如果/当前导数字的数量并不总是相同时,这将失败。尝试将第一个 60 更改为 6。此外,对于这个习惯用法,您应该使用制表符而不是逗号作为 awk 中的 OFS,因为这是排序和剪切的默认分隔符,因此您不需要分别使用 -t-d(尽管您不是在这种情况下实际上在排序中使用单独的字段,所以-t, 没有做任何事情。
  • 我必须为在这里成为一个绝对的新手而道歉。我已将代码放入 windows cmd 命令窗口,我收到错误消息,提示“-nt,系统找不到指定的文件。”和“剪切无法识别为内部或外部命令、可运行程序或批处理文件。”这是因为我没有以正确的格式调用方法“排序”和“剪切”吗?
  • 这些是unix命令,在windows中我认为你应该使用cygwin或类似的东西。我不确定awk 的 Windows 版本是否/如何工作。您也可以在 awk 脚本中实现完整的命令。
【解决方案2】:

TXR 语言的最新版本有一个 awk macro,它在 TXR Lisp 语法和语义中实现了 Awk 范式。

可能的解决方案如下所示:

;; sort list of (integer string) by the integer, ascending,
;; then extract the list of strings from the sorted result,
;; and dump it as a list of lines with tprint.

(defun sort-dump (num-rec-pairs)
  (tprint [mapcar second [sort num-rec-pairs < first]]))

;; Awk job

(awk (:begin (set fs "," ofs ","))           ;; set up I/O field separators
     (:let list)                             ;; bind local variable "list"

     ;; if we have two fields ...
     ((= nf 2) (mf int-str)                  ;; map string fields to integers
               (push (list [f 0] rec) list)) ;; push (field rec) pair to list

     ;; if we have one field ...
     ((= nf 1) (sort-dump list)              ;; dump the list
               (set list nil)                ;; clear the list
               (prn))                        ;; print current record

     (:end (sort-dump list)))                ;; dump list at end of awk job

运行:

$ txr sort.tl 数据 啊 20,14 50,123 60,312 80,143 bb 抄送 20,48 50,23 60,132 80,163

【讨论】:

【解决方案3】:

这适用于您提供的示例输入,也适用于您未提供的更有趣的输入(请参阅我在您的问题下的评论):

$ cat tst.awk
function prtArr(        a,b) {
    PROCINFO["sorted_in"] = "@ind_num_asc"
    for (a in arr) {
        for (b in arr[a]) {
            print a, b
        }
    }
    delete arr
}
BEGIN { FS=OFS="," }
/^[0-9,]+$/ { arr[$1][$2]; next }
{ prtArr(); print }
END { prtArr() }

$ awk -f tst.awk file
aa
20,14
50,123
60,312
80,143
bb
cc
20,48
50,23
60,132
80,163

上面使用 GNU awk 4.* 来处理真正的多维数组和 sorted_in。

【讨论】:

  • 感谢您的帮助。我的 PC 上没有 GNU awk 4。所以有错误消息说,函数prtArr源代码行的非法语句......这只是我正在使用的基本awk......如果你有任何关于如何每5行对4行进行排序的建议,你能告诉我吗?处理起来更简单?
  • 处理起来并不简单。只需获得 GNU awk 4.0 或更高版本,如果没有它,您将失去大量非常有用的功能。如果你在 Windows 上,那么安装/使用 cygwin 可以让你的生活更轻松,GNU awk 4 会随之而来。
猜你喜欢
  • 2017-01-26
  • 2014-05-05
  • 2018-10-29
  • 2018-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多