基于第三数字键的反向排序

时间:2016-05-23 20:17:26

标签: linux bash file sorting sh

我有一个如下所示的文件:

$ cat tmp
Albany, N.Y.    22.2    46.6    71.1    49.3    38.60   136 64.4    57
Albuquerque, N.M.   35.7    55.6    78.5    57.3    9.47    60  11.0    64
Anchorage, Alaska   15.8    36.3    58.4    34.1    16.08   115 70.8    39 / 60
Asheville, N.C. 35.8    54.1    73.0    55.2    47.07   126 15.3    39
Atlanta, Ga.    42.7    61.6    80.0    62.8    50.20   115 2.1 69 / 65
Atlantic City, N.J. 32.1    50.6    75.3    55.1    40.59   113 16.2    60 / 54
Austin, Texas   50.2    68.3    84.2    70.6    33.65   85  0.9 62 / 58
Baltimore, Md.  32.3    53.2    76.5    55.4    41.94   115 21.5    53
Baton Rouge, La.    50.1    66.6    81.7    68.1    63.08   110 0.2 52 / 46
Billings, Mont. 24.0    46.1    72.0    48.1    14.77   96  56.9    69
Birmingham, Ala.    42.6    61.3    80.2    62.9    53.99   117 1.5 60
Bismarck, N.D.  10.2    43.3    70.4    45.2    16.84   96  44.3    64
Boise, Idaho    30.2    50.6    74.7    52.8    12.19   89  20.6    64
Boston, Mass.   29.3    48.3    73.9    54.1    42.53   127 42.8    52 / 66
Bridgeport, Conn.   29.9    48.9    74.0    54.7    44.15   119 26.2    55 / 49

说,在N.Y.之后的第一行是1月的临时值。我希望在1月份基于温度进行反向排序。我有以下命令,但它并没有真正起作用,我确信有更直接的解决方案。你能指导我一下吗?

tr -s " " < tmp > outtemp |  sort -rnt" " -k3 outtemp

4 个答案:

答案 0 :(得分:2)

这似乎可以做你想要的(linux版本):

sed -E 's/[[:space:]]([[:digit:]])/\t\1/g' < tmp |  sort -rnt$'\t' -k2

例如:

$ sed -E 's/[[:space:]]([[:digit:]])/\t\1/g' < tmp |  sort -rnt$'\t' -k2
Austin, Texas   50.2    68.3    84.2    70.6    33.65   85      0.9     62 /    58
Baton Rouge, La.        50.1    66.6    81.7    68.1    63.08   110     0.2     52 /    46
Atlanta, Ga.    42.7    61.6    80.0    62.8    50.20   115     2.1     69 /    65
Birmingham, Ala.        42.6    61.3    80.2    62.9    53.99   117     1.5     60
Asheville, N.C. 35.8    54.1    73.0    55.2    47.07   126     15.3    39
Albuquerque, N.M.       35.7    55.6    78.5    57.3    9.47    60      11.0    64
Baltimore, Md.  32.3    53.2    76.5    55.4    41.94   115     21.5    53
Atlantic City, N.J.     32.1    50.6    75.3    55.1    40.59   113     16.2    60 /    54
Boise, Idaho    30.2    50.6    74.7    52.8    12.19   89      20.6    64
Bridgeport, Conn.       29.9    48.9    74.0    54.7    44.15   119     26.2    55 /    49
Boston, Mass.   29.3    48.3    73.9    54.1    42.53   127     42.8    52 /    66
Billings, Mont. 24.0    46.1    72.0    48.1    14.77   96      56.9    69
Albany, N.Y.    22.2    46.6    71.1    49.3    38.60   136     64.4    57
Anchorage, Alaska       15.8    36.3    58.4    34.1    16.08   115     70.8    39 /    60
Bismarck, N.D.  10.2    43.3    70.4    45.2    16.84   96      44.3    64

OSX

OSX上的sed以不同方式处理特殊字符。在OSX上,尝试:

sed -E $'s/[[:space:]]([[:digit:]])/\t\\1/g' < tmp |  sort -rnt$'\t' -k2

注释

管道允许您直接将一个程序的输出与另一个程序的输入连接。因此,下面不需要outtemp

tr -s " " < tmp > outtemp |  sort -rnt" " -k3 outtemp

以上内容可以替换为:

tr -s " " < tmp |  sort -rnt" " -k3
然而,仍然存在确保1月温度处于一致区域的问题。由于某些城市的名称是一个单词而其他城市的名称是两个单词,因此这很复杂。 tr -s在这里没有帮助,因为它所做的就是挤出重复。

此处的方法是使用制表符替换数字前面的所有空格。这是通过sed完成的。 (我假设城市名称以空格分隔。)通过此更改,1月温度应始终位于字段2中。

答案 1 :(得分:1)

sort -k3nr input_file但这不适用于大西洋城,新泽西州和巴吞鲁日,其中第三个字段为N.J.La.您可以使用sed删除该空格然后排序:

sed 's/\([^,]\) /\1/' input | sort -k3nr

然而,由于大西洋城将成为大西洋城,而巴吞鲁日将成为BatonRouge,这将导致产量减少。

答案 2 :(得分:0)

另一种方法是暂时插入&#34; sentinel&#34;在第一个数字之前的字符,然后将其用作排序字段分隔符,例如,

Austin, Texas   @50.2...
                ^
Baton Rouge, La.        @50.1...
                        ^

这里是如何:

sed 's/[0-9]/@&/' tmp | sort -nrk2 -t@ | tr -d @

(已测试,使用OSX&#39;(GNU coreutils)5.93)

这种方法具有多功能的优点,并且因其古怪而令人难忘。

REF:

use a temporary sentinel character

答案 3 :(得分:0)

sort -nt$'\t' -k2

以上解决方案正常。解释参数

  1. -n用于值的数字排序(第2列)

  2. t用于标签的分隔符。我们之所以使用$&#39; \ t&#39;是为了确保选项卡被正确考虑。如果有2个连续的标签只使用&#39; \ t&#39;将其视为1. $代表定界开始。

  3. -k是用于排序的列。 k代表键(列号表示值为-ka,b表示排序是从a到b的组合)
  4. 有关详细信息,请参阅以下链接。 Unix Sorting Examples