Posted on 21-04-2009
Filed Under (技术) by waterlin

如果你想用Perl读取一个目录下的所有文件名,你应该怎么办呢?一般来讲,我喜欢用两种方法。

第一种方法,直接用readdir来读取目录句柄。

use warnings;
use strict;

my $dir = “./test”;
my $file;
my @dir;

opendir (DIR, $dir) or die “can’t open the directory!”;
@dir = readdir DIR;
foreach $file (@dir) {
if ( $file =~ /[a-z]*\.zip/) {
print $file;
} else {
print “Not the kind of file type you want!\n”;
}
}

这段代码的含义就是:打开一个目录,读取所有的文件名,如果该文件名是以字母开头、并以.zip为后缀结尾的,则输出文件名称;否则,就输出提示消息。

当然,这段代码只会读取当前目录下的内容,并不会递归地寻找子目录下的内容。

第二种方法,直接用外部命令find

在Unix Shell或是Cygwin里,有命令find可以直接读出目录下的文件名,而我们只要在Perl脚本里调用这个命令就可以了。

use warnings;
use strict;

my $dir = “./test”;
my @file;
my $filename;

@file = `find $dir -type f`;

foreach $filename (@file) {
print $filename;
}

上面的代码就直接调用外部命令find来进行查找与读取。这个时候,查找的结果,完全由你所调用的外部命令所控制。

两个方法都比较方便,第一种的移植性更强,推荐使用。

(0) Comments    Read More   
Posted on 20-04-2009
Filed Under (技术) by waterlin

Perl Module是Perl语言最强大的功能,我们可以在CPAN上找到全世界Perl爱好者贡献的Module。但是,有的时候,我们自己也有代码需要可重复使用,能否把它们也做成Module,使它能方便的重复使用呢?

下面简单介绍一下Perl Module的创建方法,当然,更详细的信息,推荐仔细读一读官方的参考文档

1) 先下载一个module-starter,并安装这个Perl Module。

这个

Posted on 15-01-2009
Filed Under (技术) by waterlin

每天工作都要监视某些网页,一但这些网页有更新,就做相应的工作。

当然不能每天人工去查看每个网页了!于是我写了一个Perl脚本去自动检查。每天上班运行一下,就知道是否有更新;有更新的话,自动把内容拷贝下来,按相应的格式存到特定的文件里。

但有的时候,我需要直接把这个内容复制到其它地方,比如邮件。我同样用Perl脚本实现了这个功能:在完成了自动检查后,符合情况就自动复制到Windows的剪切板。

我觉得这里有三点值得总结一下:

1) 用Win32::Clipboard实现与Windows剪切板互动

使用这个模板,可以在命令行里直接把内容拷贝到剪切板。

use Win32::Clipboard;$CLIP = Win32::Clipboard();

print “Clipboard contains: “, $CLIP->Get(), “\n”;

$CLIP->Set(“some text to copy into the clipboard”);

$CLIP->Empty();

$CLIP->WaitForChange();
print “Clipboard has changed!\n”;

不过这玩意在Cygwin里死活装不上,只能在Strawberry Perl里用了~~

2) 让cmd或是MSYS输出中文

在Windows下,不管是cmd还是MSYS,如果直接在里面打印出中文,几乎都会乱码;而在cmd或是MSYS下,用Win32::Clipboard拷贝东西到剪切板,也同样会乱码。

需要用类似于下面的方法来改进编码的问题:

use Encode;
$infor = encode(“gbk”, decode(“UTF-8″, $_));
print $infor;

3) 响应用户的确定操作

当把内容复制到剪切板,则输出一行提示,让用户知道复制已经完成,并等待用户输入任意的一个键以示确认,再继续。这个功能很简单,可以用这个语句轻松地实现:

<STDIN>

这样的一个不起眼的小工具,却省下了我一大串繁琐的工作(比如打开文件、判断、复制内容),不亦乐乎!

(0) Comments    Read More   
Posted on 13-01-2009
Filed Under (技术) by waterlin

1) 先把目录打包,再把File::copy来复制这个打成包的文件到目的地,再解压。

推荐使用Archive::Tar作为处理压缩与解压的工具。

2) 用File::Copy::Recursive来直接拷贝目录。

(3) Comments    Read More   
Posted on 05-01-2009
Filed Under (技术) by waterlin

在Windows下刚开始使用Perl的人,很大部分都是用ActivePerl。但其实对于熟悉Linux环境下Perl编程的人来说,用Strawberry Perl会更加习惯。毕竟,ActivePerl的PPM包,更新得太慢了,如果需要自己手动编译CPAN的包,还不如用strawberry Perl来得放心呢!

Strawberry Perl其实就是windows下的the core Windows distribution of Perl的一个版本。它尽可能地在Windows平台上保持了Perl在Unix上的特性,从而也最大程度地保证了可移植性。因此,CPAN上的包,在Strawberry Perl下很容易能编译通过。

Strawberry Perl自带有以下的包

* Perl 5.10
* Mingw GCC C/C++ compiler
* Dmake “make” tool
* ExtUtils::CBuilder and ExtUtils::ParseXS
* Bundle::CPAN (including Perl modules that largely eliminate the need for external helper programs like gzip and tar)
* Bundle::LWP (providing more reliable http CPAN repository support)
* Additional Perl modules that enhance the stability of core Perl for the Win32 platform

要在Strawberry Perl下安装一个Module也非常简单,和在Unix、Cygwin等的安装比较类似。你从CPAN上下载了一个包下来,扔到一个目录里,解压后从windows的cmd命令行进入这个目录,然后运行如下的命令:

perl Makefile.PL
dmake
dmake test
dmake install

如果没有啥错误提示的话,这个包就完成了安装。不过好像Strawberry Perl并不支持在MSYS下安装CPAN包,具体原因有待进一步的分析。

(0) Comments    Read More   
Posted on 23-12-2008
Filed Under (技术) by waterlin

1) 如何在一个字符串中查找某个字符出现的次数?

原文出处:http://www.perl.com/doc/FAQs/FAQ/oldfaq-html/Q4.24.html

如果你想在一个字符串中查找字符(X)出现的次数,你可以用tr///这个函数、配合下面的方法来实现:

$string = “ThisXlineXhasXsomeXx’sXinXit”:
$count = ($string =~ tr/X//);
print “There are $count Xs in the string”;

2) 如何在一个字符串中查找某个子字符串出现的次数?

上面的代码对于你只查找单个字符来说,是非常有效的。然而,如果你试图计算多个字符组成的子字符串、在一个大字符串中出现的次数,函数tr///就不起作用了。这个时候,我们就需要加一个while循环了:

$string = “-9 55 48 -2 23 -76 4 14 -44″;
$count++ while $string =~ /-\d+/g;
print “There are $count negative numbers in the string”;

3)Perl里查询某一个文件里某一个字符串出现了多少行、以及包含该字符串的行的内容

原文出处:http://www.perlmonks.org/?node_id=650671

我们可以用如下代码实现,子过程retriver()进行读文件、查找等操作。

use strict;
use warnings;
sub retriver();
my @lines;
my $lines_ref;
my $count;
$lines_ref = &retriver();
@lines =@$lines_ref;
$count = @lines;
print “Count :$count\nLines\n”;
print join “\n”,@lines;
sub retriver()
{
    my $file = ‘source_data\data.txt’;
    open FILE, $file or die “FILE $file NOT FOUND – $!\n”;
    my @contents = <FILE>;
    my @filtered = grep(/abc:/,@contents);
    return \@filtered;
}

(0) Comments    Read More   
Posted on 23-12-2008
Filed Under (技术) by waterlin

我有一个叫a.pl的Perl脚本,里面有类似下面的读取命令行输入值的语句:

my $device_name = <STDIN>;

如果我在b.pl脚本里,用system或是readpipe命令来粘合脚本a.pl,当运行到上面这个语句的时候,命令行会提示输入一个值。

有的时候,比如说自动化脚本测试中,希望能让脚本b.pl自动输入这个值,或者说,自动在b.pl脚本里给a.pl脚本里的变量$device_name赋值。

这样,程序就可以不用人工干预,全部自动运行了。

可以在b.pl中,用类似这样的语句来实现这个功能:

system(“echo yes|perl a.pl”);

或是

my @dev_check_result = readpipe(“echo “.$dev_file.” | perl a.pl”);

这样,在调用a.pl时,在命令行提示说要输入一个值给变量$device_name的时候,就会自动把yes或是$dev_file这个值赋值给a.pl里的$device_name变量。

(0) Comments    Read More   
Posted on 16-12-2008
Filed Under (技术) by waterlin

今天在使用Perl写脚本的时候,因为做task的需要,想让Perl干掉大部分的赃活。对于每一个task,我希望新建一个形如2008_12/task_name的文件夹名来放相关的文件。这个文件夹下,还要新建若干个有特定命名规律的文件夹来分类各种文件。每次做这样的工作,耗费了大量的时间与精力,其实完全可以用Perl来自动实现。

其实,就是用Perl检查某路径下某个文件夹是否存在。如果不存在,就创建它;如果这个文件夹存在,就不干任何事。

可以用类似这样的代码来实现这个功能:

$filename = “E:/MyTaskFolder/2008_10/task_name”;
 
if(-e $filename){
 
    print “File exists.”;
 
} else {

    mkdir ($filename);

}

我是在Cygwin下实现的,在Windows Command Line下应该也是可以的。当然,有关$filename的具体值,可以根据具体情况动态生成。

(0) Comments    Read More   
Posted on 10-12-2008
Filed Under (技术) by waterlin

今天在写Perl脚本的时候,碰到一个语句:

system (“copy /y $XMLInputFile  $UpdatedXMLFile”) == 0 or die “$!\n”;

刚开始没注意,在Cygwin下死活执行不了,提示错误说:

$ perl IntruShieldSigUpdate_v1.pl input.txt
No such file or directory

后来想到了,可能copy只是Windows才有的命令,于是切换到Windows Command Line下,终于可以顺利运行了。

System调用的系统命令,与你在哪个Shell里跑有很大的关系。在Cygwin下,就只能用Cygwin能识别的命令;在Windows Command Line里,就只能用Windows Shell能识别的命令。

如果要方便移植的话,还是推荐多用一用cpan的包,比如这里就应该用File::copy来实现拷贝和移动文件的功能。不过,如果使用你脚本的人,没有安装这个File::copy包,也会碰到一系列的问题。

(0) Comments    Read More   
Posted on 14-10-2008
Filed Under (技术) by waterlin

如果要用Perl来查一个文件有多少行,怎么办?Perl Cookbook里的Counting Lines (or Paragraphs or Records) in a File就给我们讲了一些方法。

在Windows下,可以配合Cygwin里的wc来得到结果。如果你的Cygwin里已经装了wc,则直接用下面的程序就可以得到你想要的结果:

$count = `wc -l < $file`;
die “wc failed: $?” if $?;
chomp($count);

当然,如果你喜欢的话,也可以直接打开文件,一行一行地读入文件,然后得到文件的行数。

open(FILE, “< $file”) or die “can’t open $file: $!”;
$count++ while <FILE>;
# $count now holds the number of lines read

如果你的行是以“\n”结尾的话,可以这样写:

$count += tr/\n/\n/ while sysread(FILE, $_, 2 ** 16);

当然,你也可以模拟wc的形式来写这些代码,下面就是一种形式:

open(FILE, “< $file”) or die “can’t open $file: $!”;
$count++ while <FILE>;
# $count now holds the number of lines read

更加简洁的形式:

open(FILE, “< $file”) or die “can’t open $file: $!”;
for ($count=0; <FILE>; $count++) { }

还有一种更酷的写法:

1 while <FILE>;
$count = $.;

如果你要数一数有多少个段落,就参考这个代码吧:

$/ = ”;            # enable paragraph mode for all reads
open(FILE, $file) or die “can’t open $file: $!”;
1 while <FILE>;
$para_count = $.;

(0) Comments    Read More