Perl学习

Posted 生物文摘

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Perl学习相关的知识,希望对你有一定的参考价值。

7 使用外部模块、函数库或包

7.1 use Getopt::Std

我们使用其它 Unix 工具时发现, 有些工具可以带很多参数, :

$ split -l 100 -a 3 tmpfile

像上面的 -l , 可以用来指定一个参数, 并且还可以写成:

$ split -a 3 -l 100 tmpfile

这样, 我们就不需要担心参数的顺序问题了.

c , 我们使用 getopt 来处理参数( man 2 getopt),

Perl 一样提供了类似的东西, 使用起来也很简单:


use Getopt::Std;

getopt("bc:d:f:", \%arg);

# $arg{b}, $arg{c}

for (keys %arg) {

print qq/\$arg{$_} = $arg{$_}\n/

}

if ($arg{b}) {

print "-b\n";

}

$ perl t.pl -c /tmp -d /path/to/dir -f file-b

7.2 use POSIX

1. 时间处理

===========

Perl , 时间处理与 C 语言里很相似, 使用下列同名函数:

time, localtime,mktime

a. time 得到当前秒数, $curr =time;

b.localtime 返回秒数的具体描述列表, 若不指定参数, 则取当前时间.

: ($sec,$min,$hour,$mday,$mon,$year) = localtime($t);

注意返回列表中的取值范围是与 localtime(3) 中的 struct tm 一样的,

也即:

$sec 0 -> 59

$min 0 -> 59

$hour 0 -> 23

$mday 1 -> 28 29 30 31

$mon 0 -> 11

$year 年份减去 1900, 107 表示 2007


因为返回是一个列表, 所以可以这样使用: @m =localtime($t);

但是, localtime 并不是只是返回这 6 个元素, 还有其它的另外的

三个值, 如星期几, 这些通常用不到. : perldoc -f localtime


c. mktime 返回秒数, 功能与 localtime 相反.

mktime 并不是 Perl 的内置函数, 而是放在模块 POSIX 中的,

所以需要这样使用:


use POSIX;

$t =mktime($sec, $min, $hour, $mday, $mon, $year);

或者:

$t =POSIX::mktime($sec, $min, $hour, $mday, $mon, $year);

输入参数列表的范围与 localtime 的返回值一样.

这样, time,localtime, mktime 就能够完成所有的时间处理了.


1.2 2: 计算两个时间的差

有时需要计算两个给定时间的差, 或者某个时间的增量或减量,

这时需要把给定的时间先转成秒数, 再相加或相减.

例子: 计算 2007-06-0812:00:00 2007-05-3012:00:00 的差:

先写个简单的函数转成秒数:

use POSIX;

sub str2t($) {

my @m = split /[\-\s:]+/, $_[0];

@m[0, 1] = ($m[0] - 1900, --$m[1]);

mktime reverse @m

}


$t1 ='2007-06-08 12:00:00';

$t2 ='2007-05-30 12:00:00';

$tmp =str2t($t1) - str2t($t2);


1.3 3: 计算某个时间的偏移

例子: 计算 2007-6-812:0:0 的下一天或前一天:

先由 sub str2t 得到秒数, 加或减 86400 即可:


$t1 = '2007-6-812:0:0';

$next_day =str2t($t1) + 86400; # 一天的秒数是 86400

$prev_day =str2t($t2) - 86400;

printt2str($next_day), "\n";


1.4 4: 计算某月的最后一天

----------------------------

方法: 先得到下个月 1 日的秒数, 减去 86400, 即最后一天的秒数


8 引用补充

8.1 引用简介

8.2 使用引用

8.3 使用反斜线(\)操作符

8.4 引用和数组

关于Perl语言应该记住的最重要的一点可能是:Perl中的数组和哈希表始终是一维的。因此,数组和哈希表只保存标量值,不直接存贮数组或其它的复杂数据结构。数组的成员要么是数(或字符串)要么是引用。
对数组和哈希表可以象对简单变量一样使用反斜线操作符,数组的引用如下:

1 #!/usr/bin/perl
2 #
3 # Using Array references
4 #
5 $pointer = \@ARGV;
6 printf "\n Pointer Address of ARGV = $pointer\n";
7 $i = scalar(@$pointer);
8 printf "\n Number of arguments : $i \n";
9 $i = 0;
10 foreach (@$pointer) {
11 printf "$i : $$pointer[$i++]; \n";
12 }

9 实例应用

9.1 简单的 hash 应用

6.1 按关键字累加

假设有一文件 tmpfile 的内空是

aaa 5

bbb 22

ccc 2

aaa 10


我们需要按第一列为关键字累加第二列的值:

open(FH, "tmpfile") or die $!;

while ($line = <FH>) {

chomp $line; # 去掉换行

@m = split / /, $line; # 按空格分割

$hash{$m[0]} += $m[1]; # 累加

}

for $key(sort keys %hash) {

print "$key = ", $hash{$key},"\n";

}

9.2 大数问题

先看一下这一小段代码:

$n =1239482349287349;print $n, "\n";

输出结果为: 1.23948234928735e+15

这明显不是我们想要的, 当数在一个 double 的范围也即 8 字节之内,可以这样输出: printf "%.f", $n;这样结果就正确了。但是,当数很大时, 例如 $n = 123456789012345678901234 , 用上面的方法输出结果并不是我们想要的, 这时彻底的解决方法是使用模块bignum :

use bignum;

$n =123456789012345678901234;

print $n,"\n";

这样的结果才是我们想要的.

9.3 一行的 perl

$ perl -pi -e 's/aa/bb/g' file1

解释: -pi 用于对文件作替换, s/aa/bb/g $_ 中的全部 aa 替换成 bb,当使用 -pi , perl $_ 做了一些处理, 凡是对 $_ 所做的修改,最终会写回文件, 所以, 可以只对部分做替换: $ perl -pi -e 's/aa/bb/gif /xx/' file1;

$ find . -name "file*" -exec perl-pi -e 's/aa/bb/g' {} \;

这个命令使用 find 查找当前目录所有的以 "file" 开头的文件,然后调用( -exec 参数) perl 完成替换.

$ ls | perl -ane'`mv $F[0] ..`if/200801/'

注解: -a 会让 perl 自动使用 split /\s+/ 分割每一行, 结果放到 @F .

9.4 在一个文件中找出在另一文件存在的行

功能: 假设有两个手机号码文件 A B, A 中找出在 B 中的号码

方法: B Hash, 过一遍 A 即可.

先生成文件 A:

$ perl -e 'srand(time); printf"13900%06d\n",

int(rand(10**6)) for 1..10000' > A

再生成文件 B:

$ perl -e 'srand(time); printf"13900%06d\n",

int(rand(10**6)) for 1..10000' > B

查找代码:

$fileb = shift;

open FH, $fileb or die $!;

while (<FH>) {

chomp;

$h{$_} = 1;

}

while (<>) {

chomp;

print $_, "\n" if $h{$_} ==1;

}

把上面的代码存为 t.pl,然后这样运行: perlt.pl B A或者运行: perlt.pl test1:/home/perl/3.1.2 test1:/home/perl/3.1.2; 注解: int 是一个内置函数, 功能是转成整型, 例如 int(6.4) 返回 6, rand 用于产生随机数, 需要先调用 srand 设置种子, time 返回当前秒数, 关于时间的使用请见 4.perl.3.txt .

9.5 计算目录特定文件的总字节大小

#!/usr/bin/perl

use File::Find;

my $dir = shift;

sub count {

if (-f and /^\.txt/) {

$size += -s;

}

}

find(\&count, $dir);

print $size, "\n";

9.6 把文件移到另外的目录

use strict;

my $dir = shift;

my $to = shift;

opendir DIR, $dir or die "$dir:$!";

while (my $file = readdir(DIR)) {

if (not $file =~ /^\./) {

rename "$dir/$file", "$dir/$to" or die $!;

}

}

close DIR;

9.7 这个子程序是寻找@names 中“dino”的索引值

my @names = qw /fred barney betty dino Wilma pebbles bam-bamm/;

my $result = &which_element_is(“dino”,@names);

sub which_element_is{

my($what,@array) = @_;

foreach(0..$#array){ #@array元素的索引

if($waht eq $array[$_]){

return $_; #找到既返回

}

}

-1; #没有找到元素(此处是可选的)

}



2.7.3 here 文档

here 文档定义一个字结束符用紧接着<<的符号定义,这个符号可以用双引

来。同时符串,这个符号可以用双引号或单引号括起来,同时它支持插值。例如下例:

my $Price = 'right';

#here documents

Print << eof

The price is $Price.

eof

将打印出:

The price is right.

Here 文档仅仅是引号的一种可替代的形式

文档。在你可以使用单引号或者双引号的地方就

可以使用 here 。下面是一个生成html文档的例子

use strict;

my someURL =http://www.location.com;

my $html =<<ENDHTML

<HTML>

<BODY>

A HREF= ge</A></P>

</BODY>

</HTML>

ENDHTML

Open (DATAFILE, ">data.file")"could not open 'data.file' $!";

Print DATAFILE $html; to file

close(DATAFIL);

my $s

'http://www.perl.com';

NDHTML;

<P><

"$someURL">Perl Homepa

ENDHT

open(DAprint DA || die $! # print

E);

print $html; # print to STDOUT



(素材来自网络)

以上是关于Perl学习的主要内容,如果未能解决你的问题,请参考以下文章

Perl学习01 标量数据

Perl学习15之perl读excel表格

C++学习(三七六)Strawberry perl

一步一步教你学习Perl

生信学习周如何系统入门Perl

perl学习正则表达式处理文本