(十二)目录操作、字符串与排序(目录句柄、文件名通配glob、字符串函数index/substr/sprintf、高级排序sort)

一、目录操作

1.1、目录操作函数与目录句柄操作函数

(1)、目录操作函数:

  • mkdir——创建目录;
  • rmdir——删除目录;
  • chdir——改变当前工作目录;
rmdir "a";               #删除文件夹(必须是空文件夹)

mkdir "b";
mkdir "c";               #创建文件夹

chdir "b";               #改变文件夹,相当于相对路经起点变为了\Users\zhais\Documents\Perl学习\b>
mkdir "d";               #改变文件夹后,在b中创建了d文件夹

  上述三个目录操作函数,同样属于Windows系统的操作命令,可以在Windows系统的终端命令行(cmd打开)进行直接操作。

(2)、目录句柄操作函数:
  若想从目录里获取文件列表,可以使用目录句柄目录句柄与文件句柄差别不大,下面是操作目录句柄的三个函数。

  • opendir——打开目录句柄,类似关键字open;
  • readdir——读取目录句柄中的内容(目录中的文件名),类似关键字readline;
  • closedir——关闭目录句柄,类似关键字close;
$dir_to_process = "C:\\Users\\zhais\\Documents\\Perl学习";              #双反斜杠——转义斜杠

opendir DH, $dir_to_process or die "Cannot open $dir_to_process: $!";   #DH为目录句柄,$!为默认标量变量的值,发生错误时,自动打印结果
foreach $file (readdir DH){                                             #readdir关键字读取目录句柄中的所有目录
  next if $file eq "." or $file eq "..";       #过滤掉隐藏目录(.|..)
  next if -d $file;                            #过滤掉文件夹
  next unless $file =~ /\.txt$/;               #过滤掉非txt文件(条件为假时,即不以.txt结尾的文件时,才执行next,进入下一轮循环)
  
  my $fullname = "$dir_to_process//$file";                              #显示全路径名
  
  #print "$file\n";                            #只显示文件名
  print "$fullname\n";                         #显示全路径文件名
} 
closedir DH;

编译运行:
在这里插入图片描述

1.2、文件操作

1.2.1、文件名通配(glob与尖括号)

  • glob操作符或者尖括号< >实现通配
#glob新的写法——glob实现通配操作
my @files = glob "*.txt *.png";                 #文件名通配,将结果放于数组中
foreach(@files){
  print "$_\n";
}

print "\n";

#旧写法——尖括号实现通配
my @files = <*.txt *.png>;                      #文件名通配,将结果放于数组中
foreach(@files){
  print "$_\n";
}

在这里插入图片描述

1.2.2、删除文件(unlink)

  • Perl中,可以通过unlink操作符指定要删除的文件列表;不能删除目录(区别于rmdir)。
unlink "1.png";                                        #单独删除文件
unlink qw/slate bedrock lava/;                         #删除文件列表

my $success = unlink "2.jpg","4.jpg","5.jpg";          #批量多个文件,返回删除结果
print "I deleted $success files just now!\n";

unlink glob "*.jpg";                                   #使用glob统配,删除批量所有的同一类型文件

foreach my $file(glob "*.txt"){
  unlink $file or warn "failed on $file\n";            #逐一删除,检查是否删除失败
}

1.2.3、重命名文件/移动文件(rename)

  • **rename关键字用于文件的重命名,也可将文件移动到其它目录中**。
rename "2.png", "2_new.png";           #重命名,第一个参数为旧名字,第二个参数为新名字

rename "3.png", "c/3.png";             #移动功能,第一个参数为要移动的文件,第二个参数为移动后文件(一般移动过程中,不改变文件的名字)

1.3、修改时间戳(utime函数)

  • 当需要修改某个文件最近的更改时间或访问时间以期满其它程序,可以使用utime函数来造假
  • utime函数前两个时间是新的访问时间更改时间,其余参数是要修改的时间戳的文件列表名
my $now = time;
my $yesterday = $now - 24*60*60;       #减去一天的秒数
#print "$now\n";                       #打印一串数字
#print "$yesterday\n";                 #打印一串数字

utime $now,$yesterday, glob "*.txt";   #修改文件的时间 (所有的txt文件)

在这里插入图片描述

二、字符串及排序

2.1、字符串函数

2.1.1、index与rindex函数(查找子字符串位置)

  index函数的查找,返回的字符位置从0开始计。如果无法找到子串,则返回-1。index函数每次都会返回首次出现子字符串的位置,同时还可以加上第三个参数来指定开始搜索的位置
  rindex函数的查找,从字符串的右侧开始查找,返回的字符位置任然从左侧由0开始计数。

#字符串函数运用
my $stuff = "howdy world";
my $where = index($stuff, "wor");           #index_查找字符串的位置(从第0个开始记)
print "$where\n";                           #打印:6

my $where1 = index($stuff, "w");            #查找到第一个w即停止
print "$where1\n";                          #打印:2
my $where2 = index($stuff, "w", $where1+1); #第三个参数指定查找的起始位置
print "$where2\n";                          #打印:6
my $where3 = index($stuff, "w", $where2+1); #查找第三个w
print "$where3\n";                          #打印:-1, 表示找不到,没有了         

#上述操作——可以通过循环操作实现

my $last_slash = rindex("/etc/passwd", "/");  #rindex_从右侧开始找,计数从左侧开始(从0开始)
print "$last_slash\n";                      #打印:4

my $name = "abc/123/xyz/hello";
$where = rindex($name, "/");                #从右侧开始找第一个斜杠
print "$where\n";                           #打印:11
$where1 = rindex($name, "/", $where-1);     #第二个参数表示起始查找位置
print "$where1\n";                          #打印:7
$where2 = rindex($name, "/", $where1-1);    #第二个参数表示起始查找位置
print "$where2\n";                          #打印:3

2.1.2、substr函数(提取/替换子字符串)

  substr函数用来处理较长字符串中的一小段内容,返回截取的子字符串;
  substr函数包含三个参数:第一个为原始字符串,第二个为**从0开始计**的起始位置,第三个为子字符串的长度可省略);

#提取子字符串
my $a = substr("Fred J. Flintstone", 8 ,5);        #第一参数为给定的字符串,第二个参数为起始位,第三个参数为截取长度
print "$a\n";                                      #打印:Flint
my $b = substr("Fred J. Flintstone", 13 ,100);     #第三个参数超出界限,那就取剩余的所有,也可以省略第三个参数
print "$b\n";                                      #打印:stone
my $c = substr("Fred J. Flintstone", 13);          #可以省略第三个参数,取剩余的所有字符
print "$c\n";                                      #打印:stone

my $out = substr("some very long string", -3, 2);  #负数表示从后边开始取
print "$out\n";                                    #打印:in

#substr与index搭配使用,截取字符串
my $long = "some very long string";
my $right = substr($long, index($long, "l"));
print "$right\n";                                  #打印:long string

  substr函数除了直接返回截取子字符串外,还可以实现字符串的替换功能

#substr替换
my $string = "Hello world";
substr($string,0,5) = "Goodbye"; 
print "$string\n";                                  #打印:Goodbye world

$string  = "aaaaadddddddsssssssssssfred.....,fred...fred.";
substr($string, -20) =~ s/fred/barney/g ;           #在后20个字符范围内进行替换
print "$string\n";                                  #打印:aaaaadddddddsssssssssssfred.....,barney...barney.

#传统写法——上述代码
my $string = "Hello world";
substr($string,0,5,"Goodbye");
#$previous_value = substr($string,0,5,"Goodbye");   #$previous_value变量无用,一般忽略
print "$string\n";                                  #打印:Goodbye world
#print "$previous_value\n";

2.1.3、sprintf函数(返回字符串,但不会打印)

  sprintf函数与printf函数有相同的参数,但是区别在于sprintf函数返回的是所请求的字符串,不会直接打印出来sprintf函数可以将格式化后的字符串存放在变量里以便稍后使用
  格式化定义数字字段的前置零(%02d)表示必要时,在数字前补0以符合指定的宽度要求

#sprintf函数使用——将格式化后的字符串保存到变量里
my $now = localtime;
print "$now\n";                                      #打印:Sun Jan 31 17:21:09 2021

my($sec,$min,$hour,$day,$mon,$year,$wday,$yday,$isdst) = localtime;

my $now = ($year+1900)."/".($mon+1)."/".$day." ".$hour.":".$min.":".$sec."\n";
print "$now\n";                                      #打印:2021/1/31 17:21:9

my $now = sprintf("%4d/%02d/%02d %02d:%02d:%02d",$year+1900,$mon+1,$day,$hour,$min,$sec);    #%02d_宽度为2位,如果只有1位数,则加上0
print "$now\n";                                      #打印:2021/01/31 17:21:09

printf "%4d/%02d/%02d %02d:%02d:%02d",$year+1900,$mon+1,$day,$hour,$min,$sec;    #打印:2021/01/31 17:21:09

2.2、排序

  在第四章提到,Perl内置的sort排序操作符,是以ASCII码序对列表进行排序。但是涉及到数字大小或者不区分大小写的排序,单一的sort操作符难以实现。

#排序
my @rocks = qw/bedrocks slate rubble granite/;
my @sorted = sort(@rocks);      #按照ASCII码值大小进行排序
print "@sorted\n";              #打印:bedrocks granite rubble slate

my @numbers = (20,2,1,10);
my @result = sort @numbers;     #按照ASCII码值大小进行排序
print "@result\n";              #打印结果:1 10 2 20  (按照首位:1122排序)

2.2.1、按数字大小或不分大小写排序(<=>, cmp)

  但是,我们可以建立自己的“ 排序子程序 ”,加以实现按数字大小或者不区分大小写的排序。
  下列排序子程序中,my($a, $b) = @_代码是Perl默认执行的操作,变量 $a与 $b会被Perl自动赋值。
  在实际的大小值排序过程中会用到飞船操作符<=>,与此对应用来比骄傲字符串的操作符为:cmp

##############################上述代码的具体实现###############################
sub by_number{                  #排序子程序
  #my($a, $b) = @_;             #Perl默认执行的操作
  #if($a > $b){ 1 }elsif($a < $b){ -1 }else{ 0 };
  $a <=> $b;                    #飞船操作符
}
my @result = sort by_number @numbers;
print "@result\n";              #打印结果:1 2 10 20  (正确排序)

  实际大小顺序或不分大小写的排序代码:

my @result = sort { $a<=>$b } @numbers;
print "@result\n";              #打印结果:1 2 10 20  (正确排序)

#my @result = sort {lc($a) cmp lc($b)} qw(Cat big apple Dog cat cab);     #lc函数,转换小写
my @result = sort {"\L$a" cmp "\L$b"} qw(Cat big apple Dog cat cab);      #比较时,全部转换为\L小写字母进行比较
print "@result\n";              #打印结果:apple big cab Cat cat Dog

2.2.1、 哈希排序(键排序、值排序)

  • 排序: sort keys %elems;
  • 排序: sort { $elems{$a} <=> $elems{$b}} keys %elems;
  • 多个值排序:sort {
               $score{$b} <=> $score{$a} or          #先按值排序,(or具有短路功能)
               $a cmp $b                   #当分数相同,返回0,再按名字排序
             } keys %score;
#哈希排序
my %elems = (B => 5, Be => 4, H => 1, He => 2, Li => 3);
my @result = sort keys %elems;
print "@result\n";                                                    #打印结果:B Be H He Li(键排序)

my %elems = (B => 5, Be => 4, H => 1, He => 2, Li => 3);
#sub by_value{ $elems{$a} <=> $elems{$b}};
my @result = sort { $elems{$a} <=> $elems{$b}} keys %elems;
print "@result\n";                                                    #打印结果:H He Li Be B(值排序)

my %score = ("barney" => 195, "fred" => 205, "dino" => 35 );
my @result = sort { $score{$b} <=> $score{$a}} keys %score;           #由大到小排序
print "@result\n";                                                    #打印结果:fred barney dino(值排序)

#如果有分数一样的,按名字排序
my %score = ("barney" => 195, "fred" => 205, "dino" => 35, "banma" => 195 );
my @result = sort {
                     $score{$b} <=> $score{$a} or                     #先按值排序,(or具有短路功能)
                     $a cmp $b                                        #当分数相同,返回0,再按名字排序
                   } keys %score;                                     #由大到小排序
print "@result\n";                                                    #打印结果:fred banma barney dino(值排序)
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SD.ZHAI

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值