sort 也可能指模組: sort
sort SUBNAME LIST
sort BLOCK LIST
sort LIST

在列表內容中,這會對 LIST 進行排序並傳回已排序的列表值。在標量內容中,sort 的行為未定義。

如果省略 SUBNAME 或 BLOCK,sort 會按照標準字串比較順序進行排序。如果指定 SUBNAME,它會提供一個子常式的名稱,該子常式會傳回小於、等於或大於 0 的數字值,具體取決於如何對列表的元素進行排序。(<=>cmp 運算子在這種常式中非常有用。)SUBNAME 可以是標量變數名稱(未加下標),這種情況下,該值會提供實際要使用的子常式的名稱(或參考)。您可以提供一個 BLOCK 作為匿名內嵌排序子常式,來取代 SUBNAME。

如果子常式的原型是 ($$),要比較的元素會透過參考傳遞到 @_ 中,就像一般的子常式一樣。這比未設定原型的子常式慢,因為要比較的元素會傳遞到子常式中,作為套件全域變數 $a$b(請參閱以下範例)。

如果子常式是 XSUB,要比較的元素會推送到堆疊中,這與通常傳遞參數到 XSUB 的方式相同。$a$b 沒有設定。

要進行比較的數值總是透過參考傳遞,且不應變更。

您也無法使用 perlsyn 中所述的任何迴圈控制運算子,或使用 goto 退出排序區塊或子常式。

use locale(但非 use locale ':not_characters')生效時,sort LIST 會根據目前的排序慣例來對 LIST 進行排序。請參閱 perllocale

sort 會傳回原始清單中的別名,就像 for 迴圈的索引變數會對清單元素產生別名一樣。亦即,變更 sort 傳回清單中的元素(例如,在 foreachmapgrep 中),實際上會變更原始清單中的元素。在撰寫明確的程式碼時,通常應避免這樣做。

Perl 在過去對於排序是否預設為穩定排序而有不同的變化。如果穩定性很重要,可以使用 sort 實用指令明確地加以控制。

範例

# sort lexically
my @articles = sort @files;

# same thing, but with explicit sort routine
my @articles = sort {$a cmp $b} @files;

# now case-insensitively
my @articles = sort {fc($a) cmp fc($b)} @files;

# same thing in reversed order
my @articles = sort {$b cmp $a} @files;

# sort numerically ascending
my @articles = sort {$a <=> $b} @files;

# sort numerically descending
my @articles = sort {$b <=> $a} @files;

# this sorts the %age hash by value instead of key
# using an in-line function
my @eldest = sort { $age{$b} <=> $age{$a} } keys %age;

# sort using explicit subroutine name
sub byage {
    $age{$a} <=> $age{$b};  # presuming numeric
}
my @sortedclass = sort byage @class;

sub backwards { $b cmp $a }
my @harry  = qw(dog cat x Cain Abel);
my @george = qw(gone chased yz Punished Axed);
print sort @harry;
    # prints AbelCaincatdogx
print sort backwards @harry;
    # prints xdogcatCainAbel
print sort @george, 'to', @harry;
    # prints AbelAxedCainPunishedcatchaseddoggonetoxyz

# inefficiently sort by descending numeric compare using
# the first integer after the first = sign, or the
# whole record case-insensitively otherwise

my @new = sort {
    ($b =~ /=(\d+)/)[0] <=> ($a =~ /=(\d+)/)[0]
                        ||
                fc($a)  cmp  fc($b)
} @old;

# same thing, but much more efficiently;
# we'll build auxiliary indices instead
# for speed
my (@nums, @caps);
for (@old) {
    push @nums, ( /=(\d+)/ ? $1 : undef );
    push @caps, fc($_);
}

my @new = @old[ sort {
                       $nums[$b] <=> $nums[$a]
                                ||
                       $caps[$a] cmp $caps[$b]
                     } 0..$#old
              ];

# same thing, but without any temps
my @new = map { $_->[0] }
       sort { $b->[1] <=> $a->[1]
                       ||
              $a->[2] cmp $b->[2]
       } map { [$_, /=(\d+)/, fc($_)] } @old;

# using a prototype allows you to use any comparison subroutine
# as a sort subroutine (including other package's subroutines)
package Other;
sub backwards ($$) { $_[1] cmp $_[0]; }  # $a and $b are
                                         # not set here
package main;
my @new = sort Other::backwards @old;

## using a prototype with function signature
use feature 'signatures';
sub function_with_signature :prototype($$) ($one, $two) {
    return $one <=> $two
}

my @new = sort function_with_signature @old;

# guarantee stability
use sort 'stable';
my @new = sort { substr($a, 3, 5) cmp substr($b, 3, 5) } @old;

警告:對函式傳回的清單進行排序時,需要小心語法。如果您要對函式呼叫 find_records(@key) 傳回的清單進行排序,可以使用

my @contact = sort { $a cmp $b } find_records @key;
my @contact = sort +find_records(@key);
my @contact = sort &find_records(@key);
my @contact = sort(find_records(@key));

如果您要使用比較常式 find_records() 對陣列 @key 進行排序,可以使用

my @contact = sort { find_records() } @key;
my @contact = sort find_records(@key);
my @contact = sort(find_records @key);
my @contact = sort(find_records (@key));

$a$b 會在呼叫 sort() 的套件中設定為套件全域變數。這表示在 main 套件中為 $main::a$main::b(或 $::a$::b),在 FooPack 套件中為 $FooPack::a$FooPack::b,依此類推。如果排序區塊在 $a 和/或 $bmystate 宣告範圍內,您必須在排序區塊中寫出變數的完整名稱

package main;
my $a = "C"; # DANGER, Will Robinson, DANGER !!!

print sort { $a cmp $b }               qw(A C E G B D F H);
                                       # WRONG
sub badlexi { $a cmp $b }
print sort badlexi                     qw(A C E G B D F H);
                                       # WRONG
# the above prints BACFEDGH or some other incorrect ordering

print sort { $::a cmp $::b }           qw(A C E G B D F H);
                                       # OK
print sort { our $a cmp our $b }       qw(A C E G B D F H);
                                       # also OK
print sort { our ($a, $b); $a cmp $b } qw(A C E G B D F H);
                                       # also OK
sub lexi { our $a cmp our $b }
print sort lexi                        qw(A C E G B D F H);
                                       # also OK
# the above print ABCDEFGH

妥善處理後,您可以混合套件和 my(或 state)$a 和/或 $b

my $a = {
   tiny   => -2,
   small  => -1,
   normal => 0,
   big    => 1,
   huge   => 2
};

say sort { $a->{our $a} <=> $a->{our $b} }
    qw{ huge normal tiny small big};

# prints tinysmallnormalbighuge

$a$b 隱含地是 sort() 執行中的區域變數,且在完成排序後會回復其原先的數值。

使用 $a$b 撰寫的排序子常式會繫結到其呼叫的套件。將它們定義在不同的套件中是可行的,但興趣不大,因為子常式仍必須參照呼叫套件的 $a$b

package Foo;
sub lexi { $Bar::a cmp $Bar::b }
package Bar;
... sort Foo::lexi ...

使用原型版本(見上文)以取得更通用的替代方案。

比較函數必須有行為。如果它傳回不一致的結果(例如,有時說 $x[1] 小於 $x[2],有時又說相反),則結果未定義良好。

因為 <=> 在任一運算元為 NaN(非數字)時傳回 undef,因此在使用比較函數(例如 $a <=> $b)對可能包含 NaN 的任何清單進行排序時要小心。以下範例利用 NaN != NaN 來從輸入清單中移除任何 NaN

my @result = sort { $a <=> $b } grep { $_ == $_ } @input;

在此版本的 perl 中,sort 函數是透過合併排序演算法實作的。