Perl字符串与排序

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

你可能感兴趣的:(Syntax,Perl,脚本语言)