Perl字串與排序
阿新 • • 發佈:2018-12-30
Perl字串與排序
1. 字串操作函式
1.1 index() 字串查詢函式
- index 可以用於查詢給定的字串a是否出現在某個字串b中,其實就是找到a在b中出現的位置;
- 找到匹配字元返回index,否則返回-1;
- 用法1: index($str1,$str2)
- 含義:查詢 $str2 在 $str1 中出現的位置,從字串首位開始查詢;
- 用法2: index($str1,$str2,$number)
- 含義:查詢 $str2 在 $str1 中出現的位置,$number為查詢到起始位置,限制返回的最小值;
#!/usr/bin/perl
my $stuff = "Hello, world world";
my $where = index($stuff,"wor"); # $where=7,因為H的索引為0,所以world中w的索引值為7
my $where1 = index($stuff,"wor",$where+1); # $where=7,因為索引的起始位置是8,所以第二個world中w的索引值為13
my $where2 = index($stuff,"wor",$where1+1); # $where=14,未找到匹配字串,返回 -1
# 迴圈查詢
my $stuff = "Hello, world world";
my @where = ();
my $where = -1;
while (1) {
$where = index($stuff,"wor",$where+1);
last if $where == -1;
push @where,$where;
}
say "Positions are @where";
- rindex 可以用於查詢給定的字串a是否出現在某個字串b中,反向查詢,從字串的末尾開始查詢;
- 用法1: rindex($str1,$str2)
- 含義:查詢 $str2 在 $str1 中出現的位置,從字串末尾開始;
- 用法2: rindex($str1,$str2,$number)
- 含義:查詢 $str2 在 $str1 中出現的位置,$number為查詢到起始位置,$numner限制了返回的最大值;
#!/usr/bin/perl
my $stuff = "yabba dabba doo";
my $where = rindex($stuff,"abba"); # $where=7,
my $where1 = rindex($stuff,"abba",$where-1); # $where=1,因為索引的起始位置是6,向前匹配
my $where2 = rindex($stuff,"abba",$where1-1); # $where=-1,起始查詢位置為0,未找到匹配字串,返回 -1
# 迴圈查詢
my $stuff = "yabba dabba doo";
my @where = ();
my $where = length $stuff; # 通過length函式返回
while (1) {
$where = index($stuff,"abba",$where-1);
last if $where == -1;
push @where,$where;
}
say "Positions are @where";
1.2 substr() 操作子字串
- substr可以用於處理較長字串中的一小部分:子字串提取
- 返回指定位置的子字串。
- 用法1: substr ($string,$initial_position,$length)
- 含義:從$initial_position位置開始查詢,取出$length長度的字串;如果$initial_position為負值,表示從字串結尾的倒數第三個字元開始處理,(最後一個字串為-1),取出對應長度的字串;
- 用法2: substr ($string,$initial_position)
- 含義:如果第三個引數省略,代表取回$string中從$initial_position位置至末尾的所有字元;
#!/usr/bin/perl
my $stuff = "yabba dabba doo";
my $sub = substr($stuff,3,2); # $sub="ba"
my $sub = substr($stuff,7); #取回從7開始的所有字串 $sub="abba doo"
my $sub = substr($stuff,-3,2); # $sub="do"
my $sub = substr($stuff,-5); #取回從-5開始的所有字串 $sub="a doo"
my $sub = substr($stuff,index($stuff,"o")); #和index的聯合使用,取回從字元“o”開始的所有字元,$sub="oo"
- substr可以用於處理較長字串中的一小部分:子字串插入/替換/刪除
#!/usr/bin/perl
my $stuff = "yabba dabba doo";
substr($stuff,0,5) = "Goodbye"; # $stuff="Goodbye dabba doo",移除從0開始的5個字元,並插入新的字串
substr($stuff,8,0) = "abc "; #第三個引數為零,不移除任何內容只插入,$stuff="Goodbye abc dabba doo"
substr($stuff,-15) =~ s/abc/xyz/; #只處理最後的20個字元,$stuff="Goodbye xyz dabba doo"
#使用傳統的四個引數方法呼叫
substr($stuff,0,5,"Goodbye"); # $stuff="Goodbyeye xyz dabba doo",移除從0開始的5個字元,並插入新的字串
1.3 sprintf() 格式化字串
- sprintf 和 printf 具有相同的引數,但是返回的是結果字串,而不會直接打印出來。
- 可以將格式化後的字串存放在變數中,以備後續使用。
#!/usr/bin/perl
my $data_tag = sprintf
"%4d/%02d/%02d %2d:%02d:%02d",
$yr,$mon,$day,$h,$min,$sec; #可能得到:2018/01/19 3:00:08 這種類似的結果
my $money = 123456789.0456;
my $mon = sprintf "%.2f",$money; #$mon = 123456789.05, 進行數字處理
- %nd 中 n 表示輸出位寬為n,如果輸出格式小於 n 用空格在左邊補齊;
- %0nd中 n 表示輸出位寬為n,如果輸出格式小於 n 用0在左邊補齊;
2. 高階排序
2.1 排序規則子程式
Perl 允許使用者建立自定義的排序規則子程式,用於解釋具體的排序規則;
Perl 知道如何進行列表的排序,依次比較列表中的兩個數字,然後按照順序排列,Perl已經幫我們做好了這些,我們只需要告訴Perl如何比較兩個數字即可,Perl會幫助我們完成其他的處理。
- 排序子程式和定義和普通子程式的定義基本一致,他會被反覆呼叫,每次都檢查列表中的兩個元素
#!/usr/bin/perl
sub any_sort { # 實際上這麼寫不能正確工作,這裡只是為了方便說明問題
my ($a,$b) = @_; # 宣告兩個變數並給他們賦值
#進行$a $b的比較
...
}
也許宣告一次 $a,$b並賦值不會耗費多少時間,但是當子程式被呼叫成千上萬次的話,這些時間將會嚴重影響程式的處理速度。因此我們不需要這麼做,Perl已經為我們做好了,$a 和 $b將會是來自原始列表的元素,沒有對他們進行宣告和賦值,他們不過是列表中的原始元素在子程式中的別名而已,因此對$a和$b的操作是會改變原始列表中的值的,因此這裡應該十分注意,儘量不要修改這兩個變數的值。
- 如果在變數列表中$a應該排在$b的前面,排序子程式返回 -1;
- 如果在變數列表中$a應該排在$b的後面,排序子程式返回 1;
- 如果在變數列表中$a和$b的值相等,排序子程式返回 0;
#!/usr/bin/perl
sub by_number {
if ($a<$b) {-1} elsif ($b>$a) {1} else {0} #我們不需要宣告$a和$b,我們只需要之處他們的比較規則
}
#排序子程式的呼叫
my @results = sort by_number @some_number;
- 其實,perl為我們定義了數字和字串的三路比較符 <=> cmp
- 如果$a $b是數字,$a <=> $b 的比較結果
- $a<$b 返回 -1,$a=$b 返回0,$a>$b 返回1
- 如果$a $b是字串,$a cmp $b 的比較結果
- $a lt $b 返回 -1,$a eq $b 返回0, $a lt $b 返回1
現在我們可以使用 <=> 進行排序了:
#!/usr/bin/perl
my @results = sort {$a <=> $b} @some_number; #使用花括號將$a $b的比較規則括起來
my @results = reverse sort {$a <=> $b} @some_number; #使用reverse進行倒序排序
my @results = sort {$b <=> $a} @some_number; #不適用reverse進行倒序排序
第三行排序語法中,我們將$a 和 $b 對換位置,就可以實現倒序排序,因為<=>和cmp時段是的,他們並不知道那個是a哪個是b,只知道左右,所以我們如果把$a和$b對調,比較操作就會得到相反的結果。
2.2 按照雜湊值進行排序
#!/usr/bin/perl
my %score = (
"barney" => 87,
"fred" => 96,
"dino" => 78,
);
my @winner = sort by_score keys %score; #採用by_score的機制進行排序,對得到的keys按照其value進行排序
sub by_score { $score{$b} <=> $score{$a}} #不適用$a和$b,改為使用其對應的雜湊值進行比較,a和b交換位置,表示數字較大的排在前面,降序排列
print @winner\n; #結果:fred barney dino
2.3 按多個鍵進行排序
#!/usr/bin/perl
# 兩級排序
my %score = (
"barney" => 87,
"fred" => 96,
"dino" => 78,
"aock" => 78,
);
my @winner = sort by_score_and_name keys %score; #採用by_score的機制進行排序,對得到的keys按照其value進行排序
sub by_score_and_name {
$score{$b} <=> $score{$a} #先按照分數進行排列
or
$a cmp $b #如果分數相同,按照名稱進行排序
}
print @winner\n; #結果:fred barney aock dino
- 當然,除了兩級排序,我們還可以進行多級排序,例如圖書館對借閱者編號ID進行五級排序,五個等級分別是未交罰金$fines, 目前借閱書本數目 $number, 姓名$name, 先按照family_name排序,再按照personal_name排序,最後是借閱者的ID,以防止前面的資訊都相同;
#!/usr/bin/perl
@patron_IDs = sort {
$fines{$b} <=> $fines{$a} or #數字標量使用 <=> ,降序排列
$number{$b} <=> $number{$a} or
$family{$b} cmp $family{$a} or #字串標量使用 cmp,降序排列
$person{$b} cmp $person{$a} or
$a <=> $b; #ID按照升序排列
} @partron_ID