Труба в Perl для сортировки и труба для другой команды - PullRequest
0 голосов
/ 01 мая 2018

Следующий фрагмент сортирует номера версий. Я проверил это в сценарии, и это кажется правильным.

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 голосов
/ 02 мая 2018
numbers_generator |
perl -Mversion -le'
   chomp( @a = <> );
   print for sort { version->parse($a) cmp version->parse($b) } @a;
' |
other_command
0 голосов
/ 02 мая 2018

Сравнение длин массивов не имеет смысла.

Достаточно сравнить первую пару или вторую, если первая и та же самая для третьей:

   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
0 голосов
/ 02 мая 2018

Вы можете сделать это проще и надежнее с помощью стандартного модуля версии .

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 как Бенджамин В. предложил .

0 голосов
/ 02 мая 2018

Вам не обязательно использовать Perl здесь. Вы можете использовать sort, указав . в качестве разделителя полей, а затем отсортировав каждое поле n в уме

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

Обратите внимание, что это для до трехзначных номеров версий.

Редактировать: до

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...