Posted on 10-10-2008
Filed Under (技术) by waterlin

在Perl脚本中,允许调用系统的命令来进行操作。这就是Perl灵活性的体现,作为一种系统命令的粘合语言,能给程序员带来许多的便利。这样,你就可以最大限度地利用别人的成果,用不着自己使劲造轮子了。

在Perl中,可以用systemexecreadpipe这三个命令来调用其他脚本、系统命令等。这三个命令的主要区别就是返回值。

1) 对于system这个函数来说,它会返回执行后的状态,比如说

@args = (“command”, “arg1″, “arg2″);
system(@args) == 0
or die “system @args failed: $?”

当然,你也可以用类似于下面的语句来检查出错的原因:

if ($? == -1) {
print “failed to execute: $!\n”;
}
elsif ($? & 127) {
printf “child died with signal %d, %s coredump\n”,
($? & 127),  ($? & 128) ? ‘with’ : ‘without’;
}
else {
printf “child exited with value %d\n”, $? >> 8;
}

2) 而对于exec这个函数来说,仅仅是执行一个系统的命令,一般情况下并没有返回值。exec只有在系统没有你要执行的命令的情况下,才会返回false值。

exec (‘foo’)   or print STDERR “couldn’t exec foo: $!”;
{ exec (‘foo’) }; print STDERR “couldn’t exec foo: $!”;

3) 当我们需要保存系统命令运行的结果,以便分析并作进一步的处理时,就要用到readpipe这个函数了。例如:

@result = readpipe( “ls -l /tmp” );
print “@result”;

会产生如下的结果:

drwxr-xr-x  2 root   root    4096 Mar 19 11:55 testdir

当然,你也可以把生成的结果放到一个文件里,以便写工作日志呀、发布报告呀。

$inject_command = “./ConfigChecker.bat F:/nic/3502/ARRAY-4AD2E0573/etc “.$device_name;
chdir “F:/TestTools/bin/”;
@temp_result = readpipe($inject_command);
open(result_file,”>result.txt”);
print result_file @temp_result;
close(result_file);

这样,你就把系统运行的结果扔到了系统命令所在目录下的result.txt文件里了。

这三个命令,有各自的特点,需要在使用时灵活选用,更详细的资料就得上PerlDoc上找了。

(2) Comments    Read More   
Posted on 04-09-2008
Filed Under (技术) by waterlin

1、文件名前面没有”>”表示读文件

open(FILE,”~/test.txt”);
while(<FILE>)
{
chomp;
print “$_\n”;
}
close(FILE);

2、文件名前面有一个”>”表示写文件,并覆盖原有内容

open(FILE,”>~/test.txt”);
print FILE “Welcome to Perl\n”;
close(FILE);

3、文件名前面有两个”>”表示在这个文件后面追加内容

open(FILE,”>>~/test.txt”);
print FILE “Welcome to Perl again\n”;
close(FILE);

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

最近因为工作需要,一直要监视几个网页,如果有更新,就要对它们进行一些处理。每天不停地刷网页,太无聊太痛苦了,于是用Perl写了一个自动监视网页并提取相关信息的东西。

首先,要装上LWP::UserAgentHTML::Manipulator这两个Perl模块。整体思路是用LWP::UserAgent模块读取特定网页下来,然后再用HTML::Manipulator来对保存下来的html进行操作,分离出你想要的部分。

1) 用LWP::UserAgent来操作网页十分简单,基本上以下几个步骤就搞定了:

use LWP::UserAgent;
$ua = LWP::UserAgent->new;
$ua->agent(“MyApp/0.1 “);
print “Please input the url you want to save:\n”;
chomp($url = );

# Create a request
my $req = HTTP::Request->new(POST => $url);
$req->content_type(‘application/x-www-form-urlencoded’);
$req->content(‘query=libwww-perl&mode=dist’);

# Pass request to the user agent and get a response back
my $res = $ua->request($req);

# Check the outcome of the response
if ($res->is_success) {
#do whatever you want to do here
}
else {
print $res->status_line, “\n”;
}

2) 读取了网页后,就可以用HTML::ManipulatorHTML::Manipulator::extract_title把该网页的标题读出来,用HTML::Manipulator::extract_content把你关心的某一部分内容读取出来,例如:

my $title = HTML::Manipulator::extract_title($res->content);
my $content = HTML::Manipulator::extract_content($res->content, ‘articleBody’);

就是读取html里id为articleBody部分的内容。

我在写我的程序的时候,还用了delHtml函数来对读取出来的内容进行了进一步的格式化,把里面多余的html代码去掉了。如里需要程序自动判断网页是否从特定时间开始有无更新,则需要用上LWP::UserAgentif-modified-since了。

(1) Comment    Read More   
Posted on 27-08-2008
Filed Under (技术) by waterlin

最近在公司里要对一些固定模式的网页进行处理,我要从定位好的位置开始,去掉html代码从而提取出文字内容。于是写了一个Perl函数来干这个活,中心思想是用正则表达式替换掉html里面的tag。

sub delHtml{
my $str = shift;
$str =~ s/<(style|script|iframe|object|embed)(?=\s|>).+?<\/\1>//igs;
$str =~ s/on(click|mouseover|mousedown|load)=”.+?”//igs;
$str =~ s/on(click|mouseover|mousedown|load)=.+?\s+?//igs;
$str =~ s/ //igs;
$str =~ s/<[^>]+?>//gs;
return $str;
}

(1) Comment    Read More   
Posted on 07-08-2008
Filed Under (技术) by waterlin

在Perl中如果需要写有关文件移动或是拷贝的命令,可以使用kurila-1.11_0下面的File::Copy模块来实现这个功能。

使用起来相当的简单与灵活:

use File::Copy;

copy(“file1″,”file2″) or die “Copy failed: $!”;
copy(“Copy.pm”,\*STDOUT);
move(“/dev1/fileA”,”/dev2/fileB”);

use File::Copy “cp”;

$n = FileHandle->new(“/a/file”,”r”);
cp($n,”x”);

(2) Comments    Read More   
Posted on 07-08-2008
Filed Under (技术) by waterlin

通常,大家都习惯于用XML写配置文件或是描述一些简单的数据结构。其实,在Perl中,用YAML更好。有关YAML的详细说明,请参看这里:http://www.yaml.org/spec/

YAML是一个很适合人类阅读的标记语言,可以被大多数的现代语言用来作数据结构。

Perl的YAML.pm模块可以直接上CPAN下载,官方网页是:

http://search.cpan.org/~ingy/YAML-0.66/lib/YAML.pm

基本上读一读下面这段英文,就明白YAML怎么用了。

    use YAML;

    # Load a YAML stream of 3 YAML documents into Perl data structures.
    my ($hashref, $arrayref, $string) = Load(<<'...');
    ---
    name: ingy
    age: old
    weight: heavy
    # I should comment that I also like pink, but don't tell anybody.
    favorite colors:
        - red
        - green
        - blue
    ---
    - Clark Evans
    - Oren Ben-Kiki
    - Ingy döt Net
    --- >
    You probably think YAML stands for "Yet Another Markup Language". It
    ain't! YAML is really a data serialization language. But if you want
    to think of it as a markup, that's OK with me. A lot of people try
    to use XML as a serialization format.

    "YAML" is catchy and fun to say. Try it. "YAML, YAML, YAML!!!"
    ...

    # Dump the Perl data structures back into YAML.
    print Dump($string, $arrayref, $hashref);

    # YAML::Dump is used the same way you'd use Data::Dumper::Dumper
    use Data::Dumper;
    print Dumper($string, $arrayref, $hashref);
(0) Comments    Read More   
Posted on 16-07-2008
Filed Under (技术) by waterlin

今天在Cygwin里写Perl脚本的时候,发现如果Windows的文件路径里有空格的话,Perl或是Cygwin都不能正确识别。

例如有

F:\TestTools\tasks\Unknown messages\MSisa_104756\msisa.unknown.20080321.unx

这样一个文件,在Cygwin下就不能用Perl的Open命令打开文件并读取内容。

如果把其中的Unknown messages换成UnknownMessages,则可以了。

PS:还有一点要注意的就是,在Cygwin里,你直接输入Windows风格的路径,Cygwin会自动帮你识别并转化。你不用手动把Windows风格路径里的“\”转化为Unix风格的“/”。

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

今天在写Perl脚本时,每次用正则表达式替换的内容都有可能不一样,于是,我就需要动态生成一个正则表达式。

例如,我这次的正则表达式可能是
^\w(3) \d\d
下次的表达式可能就是
^\d\d w(3)

于是我用if elsif语句根据情况选择不同的表达式,即
$express = qr/^\w(3) \d\d/
或是
$express = qr/^\d\d w(3)/

这样,我就只要一个语句$line =~ s/$express/$input_content/;就可以动态处理了。

在这里,关键是用qr这个操作符。

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

如果在使用Perl的过程中,要在终端上打印出彩色字符,可以使用CPAN中的Term::ANSIColor模块。现在简单地介绍一下这个模块的几种使用方法:

1)use Term::ANSIColor;

color()是把任意数量的颜色属性串成一个用空格分隔的字符串并存到变量color里,然后可以用普通的print方法输出彩色字符串。

例如:

print color ‘bold blue’;
print “This text is bold blue.\n”;

这样就会打印出蓝色的粗体字。

记住输出到color里的颜色属性一定要是

clear, reset, dark, bold, underline, underscore, blink, reverse, concealed, black, red, green, yellow, blue, magenta, cyan, white, on_black, on_red, on_green, on_yellow, on_blue, on_magenta, on_cyan, and on_white

这些。颜色属性不区分大小。普通颜色是设置前景色, 而在前面添加了on_的颜色就是背景色了,例如on_blue就是把背景设成蓝色。

当你打印完需要输出的消息后,记得用reset属性把颜色去掉,否则以后的内容全部都是显示成该种颜色。该语句如下:

print color ‘reset’;

一个完整的例子就是:

print color ‘bold red’;
print “The steps you can do by this auto-tool:\n”;
print color ‘reset’;

2) use Term::ANSIColor qw(:constants);

如果使用这种方法,可以直接把颜色属性放在要输出的问题前面,从而简化输出步骤。这些颜色属性有:

CLEAR, RESET, BOLD, DARK, UNDERLINE, UNDERSCORE, BLINK, REVERSE, CONCEALED, BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, ON_BLACK, ON_RED, ON_GREEN, ON_YELLOW, ON_BLUE, ON_MAGENTA, ON_CYAN, and ON_WHITE

等。

例如:
print BOLD BLUE ON_WHITE “Text”, RESET, “\n”;

如果你打印完之后想清除掉字符串的格式,一定要记得在最后加上一个RESET的属性值。
例如:

use Term::ANSIColor qw(:constants);
print BOLD, BLUE, “This text is in bold blue.\n”, RESET;

3) $Term::ANSIColor::AUTORESET = 1;

对于2)的方法,如果你不想在每条打印语句后面加上RESET的话,你可以直接把$Term::ANSIColor::AUTORESET的值设为true。这样每次打印完字符,只要你的属性值之间没有逗号,系统将自动帮你清除掉颜色属性。

看一个完整的例子:

use Term::ANSIColor qw(:constants);
$Term::ANSIColor::AUTORESET = 1;
print BOLD BLUE “This text is in bold blue.\n”;
print “This text is normal.\n”;

这三种方法,使用起来各有千秋,可根据要打印的复杂程度选用。

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

在Perl脚本中,可以用chdir操作符来改变当前的工作目录,举例如下:

chdir “/etc/” or die “Cannot chdir to /etc: $!”;

(0) Comments    Read More