【问题标题】:Unix sort of version numbersUnix 类型的版本号
【发布时间】:2010-12-20 19:39:34
【问题描述】:

我有一个版本号列表,比如说它们在文件versions.txt中

1.2.100.4
1.2.3.4
10.1.2.3
9.1.2.3

我希望对它们进行排序,以便按版本排序。即:

1.2.3.4
1.2.100.4
9.1.2.3    
10.1.2.3

我尝试过使用“k”参数使用各种排序命令,但对它的理解还不够好,无法完成。任何帮助,将不胜感激。

【问题讨论】:

标签: unix sorting


【解决方案1】:

-V 选项是最好的,但我不想安装新的/其他软件,因为我的排序没有那个选项。

这是最后对我有用的命令:

sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n test.txt

来自 cmets:

  • 要颠倒顺序:sort -t. -k 1,1nr -k 2,2nr -k 3,3nr -k 4,4nr
  • 跳过v前缀:sort -t. -k 1.2,1n -k 2,2n -k 3,3n -k 4,4n

【讨论】:

  • 这正是我对 -t 的预期。 -n,正如您期望的那样,每个字段都按数字排序,字段中的相似值推迟到右侧的下一个字段。我一直很沮丧,因为我总是以这种方式行事——很高兴最终知道如何做到这一点。
  • 好问题。好答案。要反转顺序,请添加一些 'r's... sort -t. -k 1,1nr -k 2,2nr -k 3,3nr -k 4,4nr
  • 如果您的版本号以“v”开头(如 v2.7.5),那么这将允许您按第一组的第二个字符排序:sort -r -t。 -k 1.2,1n -k 2,2n -k 3,3n -k 4,4n
  • 难以置信,今天仍然有用:)
【解决方案2】:
sort -V versions.txt

来自man sort

-V, --version-sort
文本中(版本)数字的自然排序

另见Details about version sort

【讨论】:

  • sort 的哪个版本有这个?我的 GNU sort 副本(在 OS X 和 Cent OS 上)没有 -V 选项。
  • 我使用的是 Debian Sid,目前有 GNU coreutils 8.5。
  • sort -V 看起来很酷。不幸的是,安装在这个盒子上的排序不支持 -V 标志。
  • 您可以安装最新版本的 sort。这个盒子的操作系统是什么?另一种解决方案是在网上找到一个程序。只需寻找“自然排序”。我至少找到了一个 PHP 脚本。
【解决方案3】:

默认情况下,BSD 不提供-V,因此Ben 的解决方案尽可能接近。为了您的方便,我在此处发布了我们的版本,该版本能够对 <label>-<version>.<ext> 等文件进行排序:

% ls bla-*.ime | sed -Ee 's/^(.*-)([0-9.]+)(\.ime)$/\2.-1 \1\2\3/'  | sort -t. -n -k1,1 -k2,2 -k3,3 -k4,4 | cut -d\  -f2-
bla-1.ime
bla-1.0.ime
bla-1.0.0.ime
bla-1.1.ime
bla-1.1.29.ime
bla-1.2.3.ime
bla-1.2.29.ime
bla-1.2.30.ime
bla-1.3.ime
bla-1.3.0.ime
bla-1.3.1.ime
bla-1.3.10.ime
bla-1.3.20.ime
bla-1.7.ime
bla-1.11.29.ime
bla-2.3.2.ime
bla-11.2.2.ime

简短说明:

  • 列出要使用ls 排序的文件。
  • 找到版本号并在行前加上它。
  • 在这样做的同时将-1 添加到末尾以使较短的版本号首先排序(甚至在.0 之前)。如果您认为1.3 等同于1.3.0,则可以将-1 更改为0
  • 使用 Ben 建议的版本号解决方案对行进行排序。
  • 从行中去掉版本前缀。

该列表现在包含一个按版本排序的适用文件名列表。 label 部分的任何其他排序都留给读者作为练习。

【讨论】:

  • 实际上,BSD 实际上默认支持-V:至少从 2012 年开始freebsd.org/cgi/man.cgi?query=sort&sektion=1。我没有回到历史版本来查看它何时更新,但 Apple 只是在使用BSD 工具的古老副本。
  • 谢谢!不知道,但有道理。
【解决方案4】:

这个命令:

echo "1.2.100.4,1.2.3.4,10.1.2.3,9.1.2.3" | tr ',' '\n' | sort -V

给出输出:

1.2.3.4
1.2.100.4
9.1.2.3
10.1.2.3

【讨论】:

  • 这应该更具可读性:1.2.3.41.2.100.49.1.2.310.1.2.3
【解决方案5】:

在 Perl 中:

sub compare_version_numbers {
   my ($l,$r) = @_;
   my @lx = split("\\.",$l);
   my @rx = split("\\.",$r);
   my $minlen = (@lx < @rx) ? @lx : @rx;
   for (my $i=0; $i < $minlen; $i++) {
      # make numeric by multiplying with 1
      my $l_number = ($lx[$i] * 1);
      my $r_number = ($rx[$i] * 1);
      # compare with spaceship operator
      my $l_vs_r = ($l_number <=> $r_number);
      # return if decision is clear!
      if ($l_vs_r != 0) {
         return $l_vs_r
      }
      # otherwise, next part in array of version numbers
   }
   # if we are here, we could not decide - shortest entry wins!
   return @lx <=> @rx
}

【讨论】:

    【解决方案6】:
    echo "1.2.100.4,1.2.3.4,10.1.2.3,9.1.2.3" | tr ',' '\n' | sort -k1,1n
    

    输出:

    1.2.100.4
    1.2.3.4
    9.1.2.3
    10.1.2.3

    你应该能够弄清楚其余的。祝你好运

    【讨论】:

    • 这里为什么100小于3?版本 1.2.100.4 应该在 1.2.3.4 之后
    【解决方案7】:
    sort -n <versions.txt
    

    【讨论】:

    • 不,他想要的是自然排序,而不是数字排序。
    猜你喜欢
    • 2010-11-27
    • 2014-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-17
    • 2013-03-01
    • 1970-01-01
    相关资源
    最近更新 更多