在Perl脚本中,允许调用系统的命令来进行操作。这就是Perl灵活性的体现,作为一种系统命令的粘合语言,能给程序员带来许多的便利。这样,你就可以最大限度地利用别人的成果,用不着自己使劲造轮子了。
在Perl中,可以用system、exec、readpipe这三个命令来调用其他脚本、系统命令等。这三个命令的主要区别就是返回值。
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上找了。
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);
最近因为工作需要,一直要监视几个网页,如果有更新,就要对它们进行一些处理。每天不停地刷网页,太无聊太痛苦了,于是用Perl写了一个自动监视网页并提取相关信息的东西。
首先,要装上LWP::UserAgent和HTML::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::Manipulator的HTML::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::UserAgent的if-modified-since了。
最近在公司里要对一些固定模式的网页进行处理,我要从定位好的位置开始,去掉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;
}
在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”);
通常,大家都习惯于用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);
今天在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风格的“/”。
今天在写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这个操作符。
如果在使用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”;
这三种方法,使用起来各有千秋,可根据要打印的复杂程度选用。
在Perl脚本中,可以用chdir操作符来改变当前的工作目录,举例如下:
chdir “/etc/” or die “Cannot chdir to /etc: $!”;