rss· 投稿· 设为首页· 加入收藏· 繁體版
当前位置: 火魔网 » 程序开发 » Perl

Perl读书笔记-06

6. Perl基本I/O操作

    在开始处理字符串之前或许我们应该先看看Perl怎么和外部数据进行交换。前面我们使用了<STDIN>来接收程序键盘输入,这实际是是用到了Perl的文件句柄和<>操作符。

6.1 <>操作符

        <>操作符从文件句柄中读出一行,如果把文件句柄比成一个由每一行组成的数组(array),那么<>操作符就类似于pop/shift这样的函数。看下面的例子:

[root@Ora01 codes]# more p18.pl

use strict;

my @lines = ();

print("Pls input 3 line in STDIN( Keyboard ): \n");

for(my $i=0;$i<3;$i++){

    $lines[$i] = <STDIN>; #STDIN是Perl预定义的句柄,而且已经预打开。用于接收标准输入(键盘输入)

print("Your input is :\n");

foreach my $line(@lines){

    print("$line");

    如果在<>操作符中没有指定文件句柄会怎么样呢?<>会作为特殊行输入操作。文件句柄由客户自己选择,看看下面的例子:

while(defined(my $line=<>)){ #输入结束时候,<>操作符的结果为undef。

    print("$line");

#<>操作符查看@ARGV来决定使用那些文件。如果为空则使用标准输入(STDIN)

[root@Ora01 codes]# perl p19.pl

[root@Ora01 codes]# perl p19.pl "/etc/hosts"    #$ARGV[0] = 文件名

# Do not remove the following line, or various programs

# that require network functionality will fail.

127.0.0.1               localhost.localdomain localhost

10.10.10.120            Ora01.LiXiang Ora01

6.2 文件句柄

    文件句柄(filehandle)是给I/O(如文件,设备,网络套接字或者管道)起的一个名字。这可以分清楚我们正在和哪个文件或者设备通讯,同时隐藏了如缓冲等的复杂性。文件句柄能帮助我们容易地从不同的地方接收输入,并输出到不同的地方。

    文件句柄的命名规则和Perl中其它的标识符一样(由字母,数字,下划线组成,但不能数字开头);由于没有前缀,这可能和现在或者将来的保留字,标签混淆。所以取一个不容易混淆的名字很重要(和其它的标识符一样,大小写敏感)。Larry推荐文件句柄的所有字母均大写,这有利于阅读。虽然句柄名称大小写Perl都是被接受的。Perl自身预定义有六个文件句柄:STDIN, STDOUT, STDERR, DATA, ARGV, ARGVOUT。虽然可以任意给文件句柄命名,但用户定义的句柄名称不能选择上面六个,除非你要用的就是Perl预定义的那六个句柄。

    当我们可以使用一个句柄时候,需要使用open函数打开一个句柄。Open函数需要至少两个参数:文件句柄和你希望与句柄关联的文件名。(上面提到的Perl预定义的句柄是已经预先打开的,所以不需要open就能直接使用。)和C++中的数据流一样,我们需要用close函数来关闭文件句柄释放资源,当我们不需要的时候。看下面一个例子:

#使用文件句柄打开/etc/hosts文件,并打印其内容

[root@Ora01 codes]# more p20.pl

use strict;

my $filename = '/etc/hosts';

open(FH_HOSTS,$filename);

my @lines = <FH_HOSTS>;

close(FH_HOSTS);

print @lines;

        Open函数还可以创建用于不同用途(输入,输出,管道)的句柄。要创建不同用途的句柄,可以通过在文件名前面加前缀>或者>>。

Open(FILEHANDLE, $filename);  #or open(FILEHANDLE,”<$filename”);  open for input,

Open(FILEHANDLE,”>$filename”);  #open for output

Open(FILEHANDLE,”>>$filename);  #open for appending

Open(MYSTDIN,’-‘); # = <STDIN>;

Open(MYSTDOUT,’>-‘); #Open standard output.

6.3 外部程序的调用

    虽然Perl对外部操作系统程序的调用不属于I/O操作。脚本在很多时候都需要调用操作系统的一些程序(命令)来自动完成一些操作。或者Perl脚本用到一些外部程序的输出。我们来看看Perl调用外部程序的一些用法。

    我们可以通过system或者exec这两个Perl内嵌函数来对外部程序进行调用,这和C语言的做法很像。system和exec的区别是system等待外部命令执行返回再继续执行,而exec不等外部程序执行返回(要看具体区别可以使用perldoc Cf查看文档)。

#函数原型: system LIST

# my @mycmd = ("netstat","-r"); 

#my $mycmd = 'netstat -r';  参数是标量这也是可以的,应该是在某个地方自动转换成了列表了

my @mycmd = ("D:\\Program Files\\PuTTY\\putty.exe");    #可以带路径

if(system(@mycmd)){

    print("Ok.");

}else{

    print("Failed.")

        system和exec函数返回值是布尔类型表示命令执行成功或失败,而调用的程序的输出是传到Perl标准输出(显示屏)上的。有时需要将其结果作为字符串保留下来以便进一步处理。这时我们可以使用通过使用反引号(`)做到,就像shell语言一样:

#!perl

my $mycmd = "ipconfig";

my @cmdout = `$mycmd`;

foreach (@cmdout){

    print($_);

    如果我们给open函数的第二个参数后缀或者前缀一个管道符号(|),那么Perl会给我们打开一个管道而不是一个文件。然后“|”剩下的就成为一条命令,这条命令会被Perl解释成一个进程,而我们则可以从这条命令中输入或者输出数据流。

[root@demo01 codes]# vi p01.pl

#!/usr/bin/perl

use strict;

my @output = `ps -ef`;

open my $row(GREP,"|grep ora");

foreach (@output){

        print(GREP $row."\n");

Close(GREP);

#管道符在命令前面说明命令从匿名管道读取输出。程序其实等效于命令ps Cef|grep ora

#如果写成open(GREP “grep ora|”);这运行会报错: grep: (standard input): Input/output error

#并不是所有命令都能从匿名管道里读取数据的 比如说:

[root@demo01 codes]# echo "/etc/hosts"|ls -l

total 8

-rw-r--r-- 1 root root 87 Dec  7 23:45 p01.pl

-rw-r--r-- 1 root root  6 Dec  7 22:55 test.txt

#并没有变成想要的ls Cal /etc/hosts

#用open(FD,”|ls Cal”);的话其实不管往pipe里输入什么,ls Cal 都是返回当目录。

#另外一个例子是从管道里读出数据,命令在管道符后面。

[root@demo01 codes]# vi p01.pl

#!/usr/bin/perl

use strict;

open (FH,"ls -al|");

print(<FH>);     #将ls Cal的输出打印出来。

close(FH);

    我对Unix进程间的管道通信(IPC)没什么概念,单从使用外部程序调用来看,如果只是获取外部程序的输出,那么只要给open函数的第二个参数传入要执行的命令,后缀加管道符(your_command|) 就行了(也就是读管道中的数据),至于使用pipe的方式有什么好处,书中告诉我们,如果是用反引号(``),我们在命令执行完之前是得不到任何输出的,而管道方式则可以在程序执行过程中就获得程序输出。

顶一下
(0)
踩一下
(0)