-
Notifications
You must be signed in to change notification settings - Fork 448
VersionPathSorter
Vitalii Koshura edited this page Apr 2, 2023
·
2 revisions
use strict;
# Read all lines from STDIN or file
my @lines = <>;
# Remove terminating newline from each line
foreach (@lines) {
chomp
}
# Function to compare version numbers like "7.1.2"
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
}
# Function to compare whole paths like "client_release/7.2/7.2.25"
# As it is called from "sort", the values are passed in via "$a" and "$b"
sub compare_paths {
my @ax = split("/",$a);
my @bx = split("/",$b);
my $minlen = (@ax < @bx) ? @ax : @bx;
for (my $i=0; $i < $minlen; $i++) {
# Check whether we have version numbers at position $i
my $a_is_vnum = ($ax[$i] =~ /^[\d\.]+$/);
my $b_is_vnum = ($bx[$i] =~ /^[\d\.]+$/);
if ($a_is_vnum && !$b_is_vnum) {
# "a" version number before "b": b wins
return 1
}
if (!$a_is_vnum && $b_is_vnum) {
# "b" is version number before "a": a wins
return -1
}
if (!$a_is_vnum && !$b_is_vnum && $ax[$i] ne $bx[$i]) {
# both are not version numbers and both are unequal: compare the strings
return $ax[$i] cmp $bx[$i]
}
if ($a_is_vnum && $b_is_vnum && $ax[$i] ne $bx[$i]) {
# both are unequal version numbers: compare the version number
# print STDERR $ax[$i] . " vs " . $bx[$i];
my $sn = compare_version_numbers($ax[$i],$bx[$i]);
# print STDERR " = " . $sn . "\n";
if ($sn != 0) {
return $sn
}
}
# otherwise, next part in array of path elements
}
# if we are here, we could not decide - shortest entry wins!
return @ax <=> @bx
}
# Sort and print
my @sorted = sort compare_paths @lines;
foreach (@sorted) {
print "$_\n"
}