管道到perl进行排序和管道到其他命令

时间:2018-05-01 20:51:08

标签: perl

以下代码段对版本号进行排序。我在脚本中测试它似乎是正确的。

sort {
       my @left  = split( /\./, $a );
       my @right = split( /\./, $b );

       if ( $left[0] <=> $right[0] ) {
          return $left[0] <=> $right[0];
       }

       if ( $left[1] <=> $right[1] ) {
            return $left[1] <=> $right[1] 
        }
        elsif ( @left < @right ) {
            return -1;
        }

        return @left < @right ? -1 : 1;
} @versions  

如何使这个更简洁/更简洁,并在管道序列中运行它 即numbers_generator | perl -e SORT_HERE | other_command

4 个答案:

答案 0 :(得分:5)

使用标准version module可以更轻松,更可靠地完成此操作。

sort { version->parse($a) <=> version->parse($b) } @versions

至于管道,取决于接收到的是什么。您可以将它们作为命令行参数(即@ARGV)或作为stdin的行接受。您可以分开输出空格,也可以分开输出。

这里它将版本作为stdin上的行并输出为单独的行。

#!/usr/bin/env perl

use strict;
use warnings;
use v5.10;
use version;

say join "\n",
    sort {
      version->parse($a) <=> version->parse($b)
    }
    map { chomp; $_ }
    <STDIN>;

它会像这样使用。

$ echo -e '19.0\n2.9\n0.1.23.45' | sort_versions 
0.1.23.45
2.9
19.0

然后另一端逐行读取STDIN的版本。

但是如果你有GNU排序,你应该使用sort -V作为Benjamin W. suggested

答案 1 :(得分:2)

比较数组的长度毫无意义。

比较第一对,如果第一对相等,第二对相同,第三对相同,应该足够了:

   return $left[0] <=> $right[0]
       || $left[1] <=> $right[1]
       || $left[2] <=> $right[2]

您需要禁用警告,以便在比较不同长度的两个版本时不会获得“使用未初始化的值”。

因此,管道看起来像

numbers_generator \
| perl -e 'print sort { @l = split /\./, $a; @r = split /\./, $b; $l[0] <=> $r[0] || $l[1] <=> $r[1] || $l[2] <=> $r[2] } <>' \
| other_command

答案 2 :(得分:1)

numbers_generator |
perl -Mversion -le'
   chomp( @a = <> );
   print for sort { version->parse($a) cmp version->parse($b) } @a;
' |
other_command

答案 3 :(得分:0)

您不一定需要在这里使用Perl。您可以使用sort,将.指定为字段分隔符,然后按字母n对每个字段进行排序

numbers_generator | sort -t. -k 1,1n -k 2,2n -k 3,3n | other_command

请注意,这是最多 3位版本号。

修改: