加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Perl学习

发布时间:2020-12-16 00:18:09 所属栏目:大数据 来源:网络整理
导读:1、块注释,You?can read more about POD in? perldoc perlpod . = begin comment This ?content is commented? out . It may span many lines . print? "This statement won’t be executed by Perln" ; = end comment = cut print? "Hello world!n" ; ?#
1、块注释,You?can read more about POD in?perldoc perlpod.

=begin comment
This?content is commented?out.
It may span many lines.
print?"This statement won’t be executed by Perln";
=end comment
=cut
print?"Hello world!n";?# print the message

第一个“=”和“=cut”之间为注释部分。
2、使用__END__(2个_),__END__下面的部分都会被perl忽略,一般用于在perl代码中添加大量的文档。

print?;?# print the message
__END__
All text?and?code from here downwards will be ignored by Perl"This statement won’t be executed by Perln"


20100223
1、<>被用来处理所有的输入
尖括号操作(<>)是一种特殊的行输入操作。其输入可由用户选择,可能是从键盘,或者不是。
举个例子,最简单的,打印输入(其实和cat是一样的功能)

#!/usr/bin/perl
while(<</SPAN>>){
????????print;
}

我们可以在命令行中直接输入:
./print.pl read.txt?
而不需要 cat read.txt|print.pl

一个程序的调用参数(invocation arguments),通常是命令行中程序名字后面的一些“字符串”。下例中,它们是要被顺序处理的文件的名字:
./print.pl read.txt read2.txt read3.txt
将运行 print.pl(在当前目录下),它将处理文件 read.txt,再处理文件 read2.txt,最后是文件read3.txt。
如果没有命令行参数,程序将处理标准输入流.

技术上讲,<>从数组@ARGV中得到调用参数。这个数组是Perl 中的一个特殊数组,其包含调用参数的列表。

另:
由于 print 需要一些输出的字符串列表,则其参数是作为列表 context 来求值的。由于<>操作返回的是列表,则它们可很好 的一起工作:
print <>; # ‘cat’ 的源程序
print sort <>; #‘sort’ 的源程序

20100302
1、特殊变量$^I
变量$^I。默认时为 undef,此时没有什么特殊的地方。但给它设置某些串时,它使尖括号操作(<>)变得有些特殊。
我们知道尖括号(<>)的神奇特点:如果没有指定文件名,则其从标准输入流中自动打开和关闭一系列文件进行读入。但如果$^I中有字符串,这个字符串则会成为备份文件的扩展名。

!?/usr/bin/perl – w
use strict;


chomp(my $date?=?‘ date’?);
$^I?=“?.bak”;


<</SPAN>>){
s/^Date:.*/Date:?$date/;
print;
}

设此时尖括号(<>)打开的文件是 fred03.dat。它像以前那样打开它,但进行了重名名,把它叫做fred03.dat.bak。这很好,因为不在使用之前的名字。现在<>将这个新的文件作为默认的输出,因此任何内容将输出到那个文件中。while循环会从旧的文件中读入一行,更新它,再把它输出到新文件中。

$^I 另一个可能值是空串,这会修改文件,但不会将原来的文件进行备份。

20100304:
1、对 _ 这个文件句柄(此操作数为单个下划线)进行文件检测(file test),stat,
或lstat操作时,将要求Perl对前一个文件检测(file test),stat,或lstat函数的操作数进行操作,而非再一次的进行系统调用。

my @original_files?=?qw/ fred barney bettyWilma pebbles dino bam-bamm/;
my @big_old_files;?#需要移到备份磁带上去的文件
foreach@orginal_files{
blei@163.com 146 / 201 9/21/2006
push?@big_old_files,?$_
if?-s)?>?100_100?and?– A _?>?90;?#比以前的方法效率高
}

第一次检测时使用了默认的变量$_。这也更加有效率(可能除了对程序员之外),他从操作系统中得到数据。第二次检测使用了 _ 这个文件句柄。这次检测中,使用第一次检测的文件的大小信息,这是我们所需要的。
对文件句柄 _ 进行检测不同于对$_进行检测。使用$_,可能每一次的值均不同,其为当前$_中得值,使用 _ 是为了解决重复调用系统的问题。

20100429:

open F-atime?+90 ?–print|”or die “ fork:?$!”?<</SPAN>F>)?{
chomp;
printf %s?size?%dK last accessed on %sn”?,
$_,?(1023?+?-s $_)/1024,?-A $_;
}

这个例子中的find 命令查找所有在最近90天没有访问。(它们是被备份的好对象)当find 查询时,Perl等待。每当找到时,Perl会将其名字,以及一些其它信息显示出来以供进一步的分析。 如果用反引号来做,我们在find命令执行完之前是得不到任何输出的。通常在没有结束前就看见它在工作是很舒服的。

20100506:
给进程组发信号:
进程是组织成进程组的,一起对应一个完整的任务。比如,如果你运行了单个 shell 命令,这条命令是有一系列过滤器命令组成,相互之间用管道传递数据,这些进程(以及它们的子进程)都属于同一个进程组。(即子进程和父进程)
如果你给一个正数的进程号发送信号,该信号只发送给该进程,而如果你给一个负数进程号发送信号,那么该信号将发送给对应的进程组的所有进程,该进程组的进程组号就是这个负数的绝对值。
如:停止所有以941为父进程的进程:

perl?-e?"kill(HUP,-941);"


20100525:
关于时间格式
'use Date::Format; print time2str("%Y%m%d %T",time+86400);'


time2str 由Date::Format提供,+86400表示1天以后的时间,更多的格式查看perldoc? Date::Format

'use Date::Format;use Date::Parse; print time2str("%Y%m%d %T",str2time("24/May/2010:00:00:19"));'

str2time 由Date::Parse提供


20100602
将perl用于shell数字的循环


????????for?i?in?`perl?'for(0..9){print "$_ "}'`

do

....

done


????????for i in `perl?'for(00..31){$num=sprintf "d",$_;print "$num "}'`


for i in `perl -e 'for(00..31){print(sprintf "d ",$_)}'`

do

.....

done

shell 实现同样功能(详细查看man seq)

for i in `seq -s ' ' 01 31`;do printf "d " $i;done

do?

echo $i

.....

done



20100802
打印当前时间
  1. use?Date::Format;
  2. print time2str("%Y%m%d-%T"time);

use Date:Parse;
use Date:Format;
print time2str("%Y%m%d-%T"(ctime(time)



20100831
打印某个时间段的时间,可以设定输出的格式
  1. use Date;
  2. use Date;
  3. use strict;


  4. my $start=shift;
  5. my $end;
  6. my $add_seconds;
  7. my $output_format;

  8. my $time_length=length $;
  9. if?$time_length eq 13?{
  10. ????#loop?hour
  11. ????$add_seconds=3600;
  12. ????$output_format="%Y-%m-%d %H";
  13. }elsif$time_length eq 10loop?day
  14. ????$add_seconds=3600?*?24"%Y-%m-%d"}else{
  15. ????die?"Wrong input format:nloop day: YYYY-mm-ddnloop hour: YYYY-mm-dd-HH"}

  16. my $start_in_UTC=str2time$;
  17. my $end_in_UTC$end;
  18. die?"Wrong,$start later than $end"?if $start_in_UTC?gt?$end_in_UTC;

  19. my @all;

  20. while?$start_in_UTC le $end_in_UTC{
  21. ????my $this_time=time2str"$output_format"$start_in_UTC;
  22. ????push @all$this_time;
  23. ????$start_in_UTC=$start_in_UTC?+?$add_seconds}

  24. map?{print?""$_" "}?@all;
shell版本查看: http://blog.chinaunix.net/space.php?uid=1838361&do=blog&id=3079565

20101103
perl正则表达式中的1 2 3
使用捕获的buffers
例如:
/(w)1/;
匹配包含两个word的字符串。 1 表示第一个()所捕获的w

/(w)1+/; 匹配包含两个或两个以上的字符串。

嵌套捕获时,需要注意要重复的捕获的()
/((w)2){2,}/; ?注意:捕获变量的顺序按照“开括号(”的顺序指派,不管嵌套与否。

20101112:
perl 调用shell内置命令:
通常可以使用system函数或者``来执行系统命令,但是对于shell的内建命令(如alias,ulimit等,详细查看 man -k bash),这样执行时会直接报错,错误内容为无法找到文件或目录,可以通过 bash -c来执行这样的命令。而对于cd、umask等命令,应该使用PERL函数chdir、umask等来实现


20101115:
1、修改配置文件:

$selinux_file"/etc/selinux/config";
tie@data:File$selinux_file,autodefer =>0or?die $;

#(tied @data)->defer;?
foreach?)?{
?? ? ? ?s/enforcing/disabled/g?if?grep {/SELINUX/} $_;
}
#(tied @data)->flush

Normally,modifying a?Tie::File?array writes to the underlying file immediately. Every assignment like?$a[3] = ...?rewrites as much of the file as is necessary; typically,everything from line 3 through the end will need to be rewritten. This is the simplest and most transparent behavior. Performance even for large files is reasonably good.

However,under some circumstances,this behavior may be excessively slow.

autodefer =>0?
Tie::File?tries to guess when deferred writing might be helpful,and to turn it on and off automatically.

或:

Open the file in update mode ("+<"),read the whole file into an array of lines,change the array,then rewrite the file and truncate it to its current seek pointer.

?

open(F"+<"or?die?"can't read $infile: $!";
$out?=?"";
while?<</SPAN>F>)?{
????s/DATE/localtime/eg;
????$out?.=?$_;
}
seek(F,?0,?0)?"can't seek to start of $infile: $!";
print F $"can't print to $infile: $!";
truncate(F,?tell(F))?"can't truncate $infile: $!";
close(F)?"can't close $infile: $!"


2、包含递归调用

#3.disable selinux
sub?selinux_config {
????????print?"nDo you want to disable SELINUX [y/n]:";

????????given?(chomp$answer<</SPAN>>)){

????????????????when?($answer ~~ /^y(?:$|es$)/i){
????????????????????????$selinux_file="/etc/selinux/config";
????????????????????????tie(@content,Tie::File,$selinux_file,autodefer?=>?0)?or?die $!;

????????????????????????foreach?(@content)?{
????????????????????????s/enforcing/disabled/g?if?grep {/SELINUX=/}?$_;
????????????????????????}

????????????????????????system("/usr/sbin/setenforce 0 ");

????????????????????????print?"SELINUX is disabled,you didn't need to reboot.n";

????????????????}

????????????????when?($answer ~~ /^n(?:$|o$)/i){print?"SELINUX still onn"}

????????????????default {
????????????????????????print?"UNKNOW RESPONSEn";
????????????????????????
&selinux_config ;
????????????????};

????????};
}

&selinux_config


20101116:
1、Use?map??when you need to transform one list into another.
Use?grep??to ?lter a list.
Use?foreach??when you want to modify the variable in-place.


20101118:
Use Perl::Tidy ?to beautify code
echo "install Perl::Tidy"|perl -MCPAN -eshell
使用,例如:ugly.pl

use warnings;?use strict<</SPAN>>)?{?if(/d/
)?{ print?"contains numbern";?}
else?{ print?"number-freen"?} }

执行: perltidy ugly.pl
结果为:ugly.pl.tdy
;
use strict<</SPAN>>)?{
??if??(/d/)?{ print???else?? ? ? { print?"number-freen"?}
}

配置Perl::Tidy,例如,更改缩进为4,更改输出为stdout,而不是.tdy
perltidy -st -i=4 ?ugly.pl

bracing style
perltidy -st -bl -bli ugly.pl


?

use warnings;?

use strict;?

while (<>)

??{

?? ? ?if ? (/d/) { print "contains numbern"; }?

?? ? ?else ? ? ? ?{ print "number-freen" }

??}


By default,Test::PerlTidy ?uses the standard options. If you want your?
code formatted with different options,ensure that you have a? .perltidyrc?
?le in the root of your distribution or in your home directory.


20101220
scp、ssh 可以使用密码来验证的模块:
Net::OpenSSH

#3、scp files
my $ssh?=?Net:OpenSSH->new(
????????????????????????$host ????????????????????????user?>?$user ????????????????????????password?>?$password ????????????????;
die?"Can't ssh to $host: "?.?$ssh>error if $ssh->error;

$ssh>scp_put{quiet?>?0>?1}"$backup_file""$remote_dir";

#4、rm remote host old files
$ssh>system"find $remote_dir -mtime +20 -name project*|xargs rm")





另外两个模块也可以实现:
scp 可以使用密码来验证的模块:
Net::SCP::Expect

ssh,使用密码来验证
Net::SSH::Expect
?Net::SSH::Perl


#3?;¢scp files
-e $backup_file{
????????print?"tar file okn";

????????my $scpe?:SCP:Expect(host>"$host""$user""$password";
????????$scpe>scp;
}else{
????????print?"tar file falsen";
}

#4?;¢rm remote host old files
my $ssh?:SSH>new?(
????????????host?>? ????????????user? ????????????password? ????????????raw_pty?>?1
????????;

my $login_output?=?$ssh>login;
die?"Login has failed. Login output was: $login_output"?if?$login_output?~?/Last login/;

my $find_rm?>exec"find $remote_dir -mtime +20 -name project*";
#print?"$find_rmn";

$ssh>close)



20101221
使用匿名函数打印当前时间
创建匿名函数
  1. use Date::Format;
  2. my $current_timesub?{
  3. ????????time2str)
  4. };

  5. print?&$current_time."n"



20101228
对于while阻塞perl,可以将改while放到一个异步程序中,由调用程序来kill掉调用程序。
或者使用fork子进程来解决,查看:
http://blog168.chinaunix.net/space.php?uid=1838361&do=blog&id=66643

20110105
改变终端输出的颜色
Use the CPAN module Term::ANSIColor to send the ANSI color-change sequences to the user's terminal:
  1. use Term::ANSIColor qw(:constants);
  2. print RED,"Danger,Will Robinson!n",RESET;
20110111
File::Copy
The File::Copy module provides two basic functions,?copy?and?move?,which are useful for getting the contents of a file from one place to another.


20110130
关于在perl的system()中echo “@”
  1. system ("echo @")
这样写的话@会被当做数组的@符号,达不到目的,应该用下面两种方法来写:
  1. @args=("echo","@");
  2. system(@args);
  1. $a='@';
  2. system("echo $a");

20110302
数据库连接的模块
  1. #@ _MODULE_INITIAL_
  2. package Cookbook;
  3. # Cookbook.pm - library file with utility method for connecting to MySQL
  4. # via Perl DBI module
  5. use strict;
  6. use warnings;
  7. use DBI;
  8. my $db_name = "cookbook";
  9. my $host_name = "localhost";
  10. my $user_name = "cbuser";
  11. my $password = "cbpass";
  12. my $port_num = undef;
  13. my $socket_file = undef;
  14. # Establish a connection to the cookbook database,returning a database
  15. # handle. Raise an exception if the connection cannot be established.
  16. sub connect
  17. {
  18. my $dsn = "DBI:mysql:host=$host_name";
  19. my %conn_attrs = (PrintError => 0,RaiseError => 1,AutoCommit => 1);
  20. $dsn .= ";database=$db_name" if defined $db_name;
  21. $dsn .= ";mysql_socket=$socket_file" if defined $socket_file;
  22. $dsn .= ";port=$port_num" if defined $port_num;
  23. return (DBI->connect ($dsn,$user_name,$password,%conn_attrs));
  24. }
  25. #@ _MODULE_INITIAL_
  26. #@ _MODULE_END_
  27. 1; # return true
  28. #@ _MODULE_END_
注:模块文件最后一行总是返回true的语句,这是必须的。因为如果模块没有返回一个true值,perl会假设模块出现了错误,并在读取它之后退出。
将改文件放到/opt下,添加到环境变量中

export PERL5LIB=/opt
使用
    #!/usr/bin/perl -w
  1. use strict;
  2. use Cookbook;
  3. my $dbh;
  4. eval
  5. {
  6. $dbh=Cookbook::connect();
  7. print "Connect!n";
  8. };
  9. die "$@" if $@;
  10. $dbh->disconnect();
20110315
摘自《perl最佳实践》
  1. if^d+D$)
  2. 改为
  3. (m{) #匹配数字
  4. ???????$ ? #匹配非数字
  5. ???}xms)
其中:/x模式可以让正则表达式以较具可维护性的方式进行部署及说明。在/x模式下,正则表达式里的空白会被忽略掉,所以你可以人随意使用空白和换行字符以缩排和部署
需要注意的是,这样的话,数据里的空白就要用s来匹配,而不能使用“ ”来匹配
/m,在sed,awk,grep等重,^,$指“匹配任何行的开头及末尾”,但在perl中,指的是“匹配整个字符串的开头和结尾”,使用/m,可以使perl中的行为与上面的程序的行为一致。
/s,点号元字符(.)在perl中兵不是“匹配任何字符”,因为点号元字符并不匹配换行字符,使用/s可以视其也匹配换行符。

下面是一个access log日志的例子
  1. ?{1.)?#ip
  2. ????????s*?-?s?-?#nothing
  3. ????????s*?[*]?#time
  4. ????????s*?"GETs /(?:w)+/www/delivery/ta.php?trackerid=(d+)(D*[dD]*)?#url
  5. ????????s* HTTP/1.[01]"?#proto
  6. ????????s*?d+?s d+?#status byte
  7. ????????s"(?:.*?)"?#refer
  8. ????????s#agent
  9. ????????s"([A-Z0-9]{16,21})"$?#guid
  10. ?????}xms{
一个例子,取出url中的域名的域
  1. url~m{http/
  2. ??????????????????????????(
  3. ??????????????????????????s]+
  4. ??????????????????????????:com|net|org|gov|cc|biz|info|cn|tv)
  5. ??????????????????????????.cn|.hk)
  6. ????????????????????{
  7. ????????????????????????print?"$1n";
  8. ????????????????}
  9. ??elsif/
  10. ???????????????????????????
  11. ??????????????????????????S}
上面的第一个if专门用来匹配类似jzol.com.cn这种url的域名
用于测试域名:
http://e.baidu.com
http://www.etnet.com.cn
http://www.ynet.com
http://www.zol.com.cn?
http://www.isoshu.com?
http://www.online.sh.cn/?
http://www.forex.com.cn/?
http://www.17you.com/?
http://www.boosj.com/?
http://abcde.com
http://jzol.com.cn

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读