对多行列进行排序

对多行列进行排序

文中:

35 EAST 23rd Street           SOUTH AFRICA   5    600   5000000   6 
83 NORTH YELLOWLIGHT AVENUE   SOUTH AFRICA   4    700   7000000   5 
777 NEW AVENUE                SAUDIA         2    900   5000000   3 
FIVE VISA ROAD                MEXICO         3    300    500000   7 
450 JACKSON BLVD              USA            3   1500    300000   4 
25 QUEENS ROAD SOUTH          SOUTH AFRICA   1    900    400000   3

如何使用gawkorawksort来确保只有南非作为倒数第二列的升序输出?

我试过了 :

awk -F. '/SOUTH AFRICA/ {print }' | sort -n -k5  

但它似乎不起作用。

答案1

简而言之,您需要首先修复原始输入,它一开始就不一致,从而在稍后尝试运行命令时导致问题。

以下是如何解决此问题的详细信息:

检查您发布的内容

首先,我们来看看问题所在。例如,如果我们复制您发布的内容并将其另存为original_file.tsv

35 EAST 23rd Street     SOUTH AFRICA        5   600 5000000     6 
83 NORTH YELLOWLIGHT AVENUE SOUTH AFRICA    4   700 7000000     5 
777 NEW AVENUE  SAUDIA      2   900 5000000     3 
FIVE VISA ROAD      MEXICO      3   300 500000      7 
450 JACKSON BLVD        USA     3   1500    300000      4 
25 QUEENS ROAD SOUTH        SOUTH AFRICA        1   900 400000      3

乍一看显得整齐、得体。不幸的是,当我们像这样仔细查看时cat -A,您将在命令提示符上看到:

$ cat -A original_file.tsv
35 EAST 23rd Street^I^ISOUTH AFRICA^I^I5^I600^I5000000^I^I6 $
83 NORTH YELLOWLIGHT AVENUE^ISOUTH AFRICA^I4^I700^I7000000^I^I5 $
777 NEW AVENUE^ISAUDIA^I^I2^I900^I5000000^I^I3 $
FIVE VISA ROAD^I^IMEXICO^I^I3^I300^I500000^I^I7 $
450 JACKSON BLVD^I^IUSA^I^I3^I1500^I300000^I^I4 $
25 QUEENS ROAD SOUTH^I^ISOUTH AFRICA^I^I1^I900^I400000^I^I3$
  • 意思^I是“这里有一个选项卡”
  • 意思$是“这是该行的结尾”

这立即揭示了不一致之处,例如:

  • 第 1 行:35 EAST 23rd Street选项卡选项卡SOUTH AFRICA...
  • 第 2 行:83 NORTH YELLOWLIGHT AVENUE选项卡SOUTH AFRICA...

一行有两个选项卡分隔字段 1 和字段 2,下一行只有一个选项卡。每行都不相同。

sort但是,当每行如此不同时,如果每行上的分隔符或定界符的排列不一致,则无法在此处正确数据。

清理版本

看起来唯一的问题(至少在这个示例中)是双选项卡的外观,而实际上它应该是单选项卡。因此,我们应该尽可能尝试使用工具,而不是手动编辑来清理它。这里我们可以使用sed它来清理它,并将结果保存到文件中,例如我们可以调用 results clean_file.tsv

$ sed 's/\t\t/\t/g;s/ $//g' original_file.tsv  > clean_file.tsv
  • s/\t\t/\t/g搜索两个选项卡并将其替换为一个
  • ;在 sed 参数中分隔多个命令
  • s/ $//g因为某些行尾似乎有一个尾随空格,所以这里将其删除
  • >文件重定向将sed输出保存到文件中,我们称之为clean_file.tsv

clean_file.tsv好像:

35 EAST 23rd Street SOUTH AFRICA    5   600 5000000 6
83 NORTH YELLOWLIGHT AVENUE SOUTH AFRICA    4   700 7000000 5
777 NEW AVENUE  SAUDIA  2   900 5000000 3
FIVE VISA ROAD  MEXICO  3   300 500000  7
450 JACKSON BLVD    USA 3   1500    300000  4
25 QUEENS ROAD SOUTH    SOUTH AFRICA    1   900 400000  3

我们可以再次使用cat -A但现在在我们的clean_file.tsv

35 EAST 23rd Street^ISOUTH AFRICA^I5^I600^I5000000^I6$
83 NORTH YELLOWLIGHT AVENUE^ISOUTH AFRICA^I4^I700^I7000000^I5$
777 NEW AVENUE^ISAUDIA^I2^I900^I5000000^I3$
FIVE VISA ROAD^IMEXICO^I3^I300^I500000^I7$
450 JACKSON BLVD^IUSA^I3^I1500^I300000^I4$
25 QUEENS ROAD SOUTH^ISOUTH AFRICA^I1^I900^I400000^I3$

我们确实看到现在一切都是一致的,如果我们仔细计算它们,现在每行都有相同数量的字段(此处为 6),以及相同数量的选项卡(此处为 5)作为字段分隔符或字段定界符。

awk,排序

现在我们已经clean_file.tsv有了正确格式化的输入,我们现在可以运行命令,并查看:

$ awk '/SOUTH AFRICA/ {print }' clean_file.tsv | sort -t $'\t' -k5,5n
25 QUEENS ROAD SOUTH    SOUTH AFRICA    1       900     400000  3
35 EAST 23rd Street     SOUTH AFRICA    5       600     5000000 6
83 NORTH YELLOWLIGHT AVENUE     SOUTH AFRICA    4       700     7000000 5
  • -F与原始命令相比,被删除,因为用于-F指定字段分隔符,此处不需要,因为awk不执行任何字段操作,并且仅在此处用于打印SOUTH AFRICA其中匹配的行
  • -t $'\t'指定字段分隔符为制表符。
  • -k5,5从第 5 列到第 5 列排序,因为在本例中您想要倒数第二列,而这里的第 5 列是这个 6 列数据样本中的倒数第二列
  • n表示数字排序。由于默认是升序,因此我们不需要进一步指定任何内容。

因此,通过清理原始数据并运行此awksort,您现在将能够找到SOUTH AFRICA条目并按第五个字段升序对它们进行排序。

答案2

这里有两个基本问题:

  1. 您提供的内容没有字段分隔符,因此“第 5 列”没有意义。您必须编辑数据(例如,在列之间使用分号)以使“列”的概念有意义。我通常使用制表符作为列分隔符,但您可以使用数据中未出现的任何字符。
  2. 您需要告诉 sort 字段分隔符是什么。

编辑数据后,您可以执行我认为您要求的操作,如下所示:

% grep "SOUTH AFRICA" file | sort "-t;" -k5n

(假设“文件”包含您的数据)。这给出了以下输出:

25 QUEENS ROAD SOUTH;SOUTH AFRICA;1;900;400000;3
35 EAST 23rd Street SOUTH AFRICA;5;600;5000000;6 
83 NORTH YELLOWLIGHT AVENUE;SOUTH AFRICA;4;700;7000000;5 

如果您想确保南非仅在第二列中,您可以这样做:

% awk '-F;' '$2 == "SOUTH AFRICA"' file | sort '-t;' -k5n

相关内容