Perl实例
30 Aug 2021 3713字 13分 次 Perl打赏作者 CC BY 4.0 (除特别声明或转载文章外)
1 前言
最近写脚本上瘾,毕竟太懒了,懒得看那么多report。积累了一些常用的代码片段,懒得每次再写了,搁在这随时复制。🤷♂️
2 chomp
这玩意的用处是删除末尾的换行符,常跟标准输入句柄一起用,删掉输入完成时的那个回车:
chomp($Moudle_Name = <STDIN>);
一个长得很像的chop函数,用来去掉变量最后一个字符。
3 获取时间
获取本地时区时间并格式化:
my ($sec ,$min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
$mon=(sprintf "%02d", ($mon+1)); # 0-11,因此要+1
$mday=(sprintf "%02d", $mday);
$year=$year+1900; # 从1900年算起,因此要+1900
也可以获取格林尼治时间:
my ($sec ,$min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = gmtime(time);
$mon=(sprintf "%02d", ($mon+1)); # 0-11,因此要+1
$mday=(sprintf "%02d", $mday);
$year=$year+1900; # 从1900年算起,因此要+1900
这其中可以使用POSIX函数格式化:
use POSIX qw(strftime);
$time = strftime "%y%m%d",localtime;
4 获取路径
获取当前路径:
use Cwd;
my $dir = getcwd;
或者:
my $dir = $ENV{'PWD'};
需要注意的是这里的路径是脚本被运行的路径不是脚本所在路径。
5 路径、文件搜索
在当前路径下,级数可调的路径、文件搜索:
my $path = "./*";
my $series_subf = 3;
sub scan_file{
my @files = glob($_[0]);
foreach(@files){
my $series_subf = $_[1] - 1;
if(-d $_){
print "path: $_ \n";
if($series_subf > 0){
my $path = $_."/*";
scan_file($path, $series_subf);
}
}
elsif(-f $_){
print "file: $_ \n";
}
}
}
scan_file($path, $series_subf);
6 文件处理(打开、新建、删除、寻找)
6.1 打开
打开文件并逐行读取:
open( REPROCESSED_FILE, "PREPROCESSED_FILE.sv") || die "Cannot open HDL file\n";
while(<PREPROCESSED_FILE>){
……
}
close PREPROCESSED_FILE;
6.2 新建
新建文件并写入字符:
open TB_FILE, '>'."$TB_Name.sv";
print TB_FILE $Parameter;
close HDL_FILE;
6.3 删除文件
删除文件:
unlink "$TB_Name.sv";
7 变量匹配
在使用变量匹配时,容易遇到变量内有需要转义的字符的情况,可以用“\Q…\E”进行全部转义:
$x =~ /\Q$y\E/;
8 格式化输出
注意“.”前面不能有空格,否则会报错。
format list =
@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<< @<<<<<<<<<< @<<<<<<<<<<
$nm, $lt, $num, $mc
.
open FP, "> ./length_match.rpt";
select(FP);
$~ = list;
my $i = 0;
foreach(@IR_Value){
$nm = $Inst_name[$i];
$lt = $Length[$i];
$num= $Num_Master[$i];
$mc = $Match[$i++];
write;
}
close FP;
select(STDOUT); #换回标准输出
9 动态输出
想要在脚本运行时输出在terminal上的字符动态更新,其实是使用ANSI控制码把光标退回去再次打印,实现动态输出的效果:
print "\033[s"; # 保存当前光标位置
foreach(@rpt){
print "\033[u$_ "; # 恢复光标位置并覆盖打印
}
print "\n";
顺带列出常用的ANSI控制码:
控制码 | 说明 |
---|---|
[X;YH | 将光标移至第X行,第Y列的位置 |
[nA | 光标上移n行(屏幕顶端无效) |
[nB | 光标下移n行(屏幕底端无效) |
[nC | 光标右移n列(屏幕最右端无效) |
[nD | 光标左移n列(屏幕最左端无效) |
[6n | 报告光标位置 |
[s | 保存当先光标位置 |
[u | 恢复光标位置 |
[?25l | 隐藏光标 |
[?25h | 显示光标 |
[2J | 清屏 |
[K | 将光标位置开始至本行结束的所有字符清除 |
[n1;n2;…m | 设定显示字符的属性,若有两个以上设定则以分号将代码(n1;n2;…)隔开。除非重新设定,否则该属性一直被保留 |
[0I | 默认字体 |
[1I | 宋体 |
[2I | 黑体 |
[3I | 楷体 |
其中,显示字符的属性代码(即上表格第14行的“n1”“n2”…):
代码 | 意义 |
---|---|
0 | 所有属性reset,即返回默认显示模式 |
1 | 高亮显示 |
4 | 加下划线 |
5 | 闪烁显示 |
7 | 反相显示 |
8 | 不可见 |
前景 | 背景 | 颜色 |
---|---|---|
30 | 40 | 黑色 |
31 | 41 | 红色 |
32 | 42 | 绿色 |
33 | 43 | 黄色 |
34 | 44 | 蓝色 |
35 | 45 | 紫红色 |
36 | 46 | 青蓝色 |
37 | 47 | 白色 |
显示循环函数的进度和百分比的子函数,需要在循环里执行:
# 进度条子函数
sub progress_bar{
my($i,$number,$length)=@_; # 获取当前循环数,总循环数,进度条总长度
my $percent = sprintf("%.2f",$i/$number*100); # 计算当前百分比
my $n = $percent * $length / 100; # 计算进度条进度
print "$percent\% \n\[\033[s"; # 打印百分比以及换行打印进度条背景的开头,并保存光标
while($length>0){print "-";$length--;}; # 打印进度条背景
print "\]\033[u"; # 打印进度条背景的结尾,并恢复光标
while($n>0){print ">";$n--;}; # 打印进度条的进度
print "\033[1A\033[100D"; # 光标回到上一行的最左侧
if($i == $number){print "\n\n";} # 如果循环结束,则光标回归并另起一行
}
my $i;
# 执行循环
foreach(@rpt){
system("~/scripts/summary.pl $PRJ"); # 执行循环内原本的操作
my $rpt_number = @rpt;
$i++; # 当前循环数,从1开始
progress_bar($i,$rpt_number,20); # 执行进度条子函数
}
print "Complete!\n";
效果如下:
需要注意的是在循环里就不能加其它打印函数了。
10 命令行参数
可以在运行脚本时传递命令行参数,例如:
./get_csv.pl /usr/home/xx.rpt 6
在脚本中获取参数:
my $file = $ARGV[0];
my $num = $ARGV[1];
11 通过匹配元素获取数组索引值
翻了半天书也没找到,问了问GPT4.0,当场给了两个方法:
使用grep函数,它可以返回一个数组,包含所有匹配元素的索引:
my @array = ("a", "b", "c", "d", "e");
my $element = "c";
my @matches = grep { $array [$_] eq $element } 0 .. $#array;
print "@matches\n"; # 2
还可以使用List::MoreUtils模块中的first_index函数,它可以返回第一个匹配元素的索引:
use List::MoreUtils qw(first_index);
my @array = ('apple', 'banana', 'cherry', 'date');
my $index = first_index { $_ eq 'cherry' } @array;
如果不是严格相等,这两种方法也都可以换成匹配。
12 获取系统变量
可以使用特殊的哈希变量$ENV
来访问环境变量。例如系统环境变量中某个项目的路径变量为$clock_mux
,可以在perl中直接获取它:
my $clock_mux = $ENV{'clock_mux'};
告辞。