`
kankan1218
  • 浏览: 271794 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

perl 读写文件

    博客分类:
  • perl
阅读更多
用Open() 函数打开文件

打开文件的常用方法是:

open(FH, "< $filename")

or die "Couldn't open $filename for reading: $!";



open() 函数通常带有两个参数,第一个为文件句柄,用于指向打开的文件,第二个参数是文件名及模式(文件的打开模式)的混合体,如果文件被成功打开,open()函数返回true,否则为false。我们用“or”来测试该条件。

上述代码中的模式由小于字符(<)来表示。如果文件不存在,open()将返回false。此时,你可以读文件句柄,但不可以写。

大于字符表示写。如果文件不存在,就会被创建。如果文件存在,文件被清除,以前的数据将会丢失。你可以写入文件句柄,但不可以读入。

# 如果文件不存在,就创建它

open(FH, "> $filename")

or die "Couldn't open $filename for writing: $!";


如果文件不存在,添加模式(用两个大于符号表示)可以用来创建新文件,如果文件存在,该模式并不会清除原来的数据。

同“<”或“读”模式一样,你只能对文件句柄进行写操作。 (所以的写入内容都添加到文件尾)。企图进行读操作,会产生运行错误。

open(FH, ">> $filename")

or die "Couldn't open $filename for appending: $!";


通过“+<”模式,你可以既可以读文件,又可以写文件。你可以通过tell() 函数在文件内部移动,通过seek()函数进行定位。如果文件不存在,就会被创建。如果文件已经存在,原来的数据不会被清除。

如果你打算清除原来的文件内容,或者自己调用truncate() 函数,或者使用“+>”模式。

open(FH, "+> $filename")

or die "Couldn't open $filename for reading and writing: $!";


注意“+<”和“+>”的区别,两者都可以可读可写。前者为非破坏性写,后者为破坏性写。

错误

错误是如何出现的?很多地方都会出现错误:如目录不存在,文件不可写入,你的程序丢失了文件句柄等等。

你应该检查系统调用的结果 (如open() 和sysopen()),看看是否调用成功。

为了帮助用户查错,通常使用“or die()”,你应记住这些用法。首先,应写出系统调用失败(“open”)的信息。其次,应写出文件名的信息,以便修正错误时更容易地定位。第三,要写出打开文件的方式, (“for writing,”“for appending”)。第四,输出操作系统的出错信息(包含在$!中)。这样,一旦出现文件不能打开的问题,使用你的程序的用户会大体上知道为什么不能打开。有时,我们把第一个和第三个合并在一起:

or die "unable to append to $filename: $!";


如果在open() 和出错信息中都写了文件的全名,你会冒改变了open() 的风险,使得出错信息不合时宜或不正确。

# 下面会出现虚假的出错信息

open(FH, "</var/run/file.pid")

or die "Can't open /var/log/file.pod for writing : $!";

用 Sysopen()进行更多的控制
为了更好的控制文件的打开方式,可以使用 sysopen() 函数:

use Fcntl;

sysopen(FH, $filename, O_RDWR|O_CREAT, 0666)

or die "Can't open $filename for reading/writing/creating : $!";


函数 sysopen() 带有四个参数,第一个是同open()函数类似的文件句柄参数,第二个参数是不带模式信息的文件名,第三个参数是模式参数,由Fcntl 模块提供的逻辑OR运算组合起来的常数构成,第四个参数(可选),为八进制属性值(0666表示数据文件, 0777表示程序)。如果文件可以被打开,sysopen() 返回true,如果打开失败,则返回false。

不同于open()函数,sysopen()不提供模式说明的简写方式,而是把一些常数组合起来,而且,每个模式常数有唯一的含义,只有通过逻辑OR运算才能将它们组合起来,你可以设置多个行为的组合。

O_RDONLYRead-only

O_WRONLY Write-only

O_RDWR Reading and writing

O_APPEND Writes go to the end of the file

O_TRUNC Truncate the file if it existed

O_CREAT Create the file if it didn't exist

O_EXCLError if the file already existed (used with O_CREAT)


当你需要小心行事的时候,就使用sysopen() 函数,例如,如果你打算添加内容到文件中,如果文件不存在,不创建新文件,你可以这样写:

sysopen(LOG, "/var/log/myprog.log", O_APPEND, 0666)

or die "Can't open /var/log/myprog.log for appending: $!";

读入单个记录
有一个容易的方法读入filehandles:用 <FH> 操作符。在标量内容下,它返回文件中的下一个记录,或者返回未定义出错信息。我们可以使用它来把一行读入到一个变量中:

$line = <FH>;

die "Unexpected end-of-file" unless defined $line;

在循环语句中,我们可以这样写:

while (defined ($record = <FH>)) { # long-winded

# $record is set to each record in the file, one at a time

}


因为要大量进行这样的工作,通常再进行一下简化,

把记录放到$_ 中,而不是$record中:

while (<FH>) {

# $_ 每次为文件中的一个记录

}

在Perl 5.004_04中,我们可以这样做:

while ($record = <FH>) {

# $record 每次为文件中的一个记录

}


defined() 将自动加上,在Perl 5.004_04以前的版本中,该命令给出一个警示。要了解所用的Perl版本,可在命令行下打入:

perl -v

一旦我们读出了一个记录,通常打算去掉记录分隔符,(缺省值为换行符字符):

chomp($record);

Perl 4.0版本仅有chop()操作,去掉串的最后一个字符, 不管该字符是什么。chomp() 没有这么大的破坏性,如果有行分隔符存在,它仅去掉行分隔符。如果你打算去掉行分隔符,就用chomp() 来代替chop()。








读入多个记录
如果你调用<FH>,返回文件中剩余的记录。如果你处于文件尾,则返回空表:

@records = <FH>;

if (@records) {

print "There were ", scalar(@records), " records read.\n";

}


在下面的一步中,进行赋值和测试两项工作:

if (@records = <FH>) {

print "There were ", scalar(@records), " records read.\n";

}


chomp() 也可适用对数组操作:

@records = <FH>;

chomp(@records);

对于任何表达式,都可以进行chomp操作,故你可以在下面的一步中这样写:

chomp(@records = <FH>);


什么是记录?

记录的缺省定义为:“行”。

记录的定义由$/ 变量控制的,该变量存放所输入的记录的分隔符,因为换行符字符(根据定义!)是用来分隔行的,故其缺省值为串“\n”。

例如,你可以用任何你想要替换的符号来代替“\n”。

$/ = ";";

$record = <FH>; # 读入下一个用分号分隔的记录

$/可以取其它两个有趣的值:空串("") 和undef。

读入段落
$/ =""的写法是用来指示Perl读入段落的,段落是由两个或两个以上的换行符构成的文本块。这不同于设置为"\n\n",后者仅读入由两行组成的文本块。在这种情况下,将出现这样一个问题:如果有连续的空行存在,例如“text\n\n\n\n”,你既可以把它解释为一个段落 ("text"),也可以解释为两个段落 ("text", 后面跟两个换行符,以及一个空段落,后面跟两个空行。)

在读入文本时,第二个解释用途不大。如果你正在读的段落出现上述情况,你不必过滤出“空”段落。

$/ = "\n\n";

while (<FH>) {

chomp;

next unless length; # 跳过空段

# ...

}


你可以把 $/设置为undef,它用于读入后面跟着两个或多个换行符组成的段落: undef $/;

while (<FH>) {

chomp;

# ...

}


读入整个文件

$/ 的其它有趣的值为undef。如果设置为该值,就将告诉Perl,读命令将把文件的剩余部分作为一个串返回:
undef $/;
$file = <FH>;


因为改变了 $/的值,将会影响以后的每次读操作,而不仅是下一个读操作。通常,你需要将该操作限制在局部。通过下面的例子,可以把文件句柄的内容读入到一个串中:
{
local $/ = undef;
$file = <FH>;
}
记住:Perl变量可读入很长的串。尽管你的文件大小不可以超出你的虚拟内存容量的限度,你仍可以读入尽可能多的数据。
用正则表达式对文件进行操作
一旦你有个包含了整个串的变量,你可以使用正则表达式,对整个文件进行操作,而不是对文件中的某个块进行操作。有两个有用的正则表达式标记/s和/m。一般,Perl的正则表达式对行进行处理,你可以这样写:

undef $/;

$line = <FH>;

if ($line =~ /(b.*grass)$/) {

print "found $1\n";

}


如果把我们的文件填入如下内容:
browngrass

bluegrass

则输出为:

found bluegrass

它没有找到“browngrass”,这是因为$ 仅在串尾寻找其匹配, (或者在串结束前的一行)。如果在包含很多行的串中,用"^" 和"$" 来匹配,, 我们可以使用 /m ("multiline") 选项:

if ($line =~ /(b.*grass)$/m) {}

现在程序会把如下的信息输出:

found browngrass

类似地,句点可以匹配除了换行符之外的所有字符:

while (<FH>) {

if (/19(.*)$/) {

if ($1 < 20) {

$year = 2000+$1;

} else {

$year = 1900+$1;

}

}

}


如果我们从文件中读入“1981”,$_ 将包含“1981\n”。正则表达式中的句点匹配“8”和“1”, 而不匹配“\n”。这里正需要这样做,因为换行符不是日期的组成部分。

对于一个包含很多行的串,我们也许要提取其中的大的块,这些块可能会跨越行分隔符。在这种情况下,我们可以使用 /s 选项,并用句点来匹配除了换行符以外的所有字符。

if (m{<B>(.*?)</B>}s) {

print "Found bold text: $1\n";

}


此处,我用了{}来表示正则表达式的起始和结束,而不用斜杠,所以,我就可以告诉 Perl我正在匹配,起始字符为"m",结束字符为"s"。你可以把/s 和/m 选项组合使用:

if (m{^<FONT COLOR="red">(.*?)</FONT>}sm) {

# ...

}

总结
有两种方法打开文件:open()函数的特点是快速简捷,而sysopen()函数功能强大而复杂。通过 <FH> 操作符,可以读入一个记录,$/ 变量可以让你控制记录是什么。如果你打算把很多行的内容读入到一个串中,不要使用忘记/s和/m 这两个正则表达式标记。
分享到:
评论

相关推荐

    使用perl读写文件

    对学习使用Perl操作文件时写的,在开始学习对Perl文件操作时,使用了$_,导致调试了很长时间,现在改正后做笔记到此

    perl读写文件.txt

    在linux上perl对文件读写的几种方法 整体读入 逐行读入 写入

    Perl读写文件简单示例

    主要介绍了Perl读写文件简单示例,本文直接给出实现代码,需要的朋友可以参考下

    perl读写文件代码实例

    主要介绍了perl读写文件代码实例,本文直接给出实现代码,需要的朋友可以参考下

    perl读写xml文件

    NULL 博文链接:https://zhych8419-163-com.iteye.com/blog/1030013

    Perl中的文件读写学习笔记

    主要介绍了Perl中的文件读写学习笔记,本文讲解了打开、关闭文件、读文件、写文件、判断文件状态等内容,需要的朋友可以参考下

    PERL编程24学时教程.pdf

    15.4.2 在读写文件中移动 176 15.5 锁定文件 176 15.5.1 锁定UNIX和NT下的文件 178 15.5.2 在加锁情况下进行读写操作 179 15.5.3 Windows 95和Windows 98下的 加锁问题 180 15.5.4 在其他地方使用文件锁的问题 181 ...

    Perl 实例精解(第三版).pdf

    9.1.9 打开文件读写 9.1.10 管道打开 9.2 传送参数 9.2.1 ARGV数组 9.2.2 ARGV和Null文件句柄 9.2.3 eof函数 9.2.4 -i开关:原位编辑文件 9.3 文件测试 练习8 获得文件句柄 第10章 子程序和...

    Perl5语言全教程

    第五章 文件读写 一、打开、关闭文件 二、读文件 三、写文件 四、判断文件状态 五、命令行参数 六、打开管道 第六章 模式匹配 一、简介 二、匹配操作符 三、模式中的特殊字符 1、字符 + 2、字符 []和[^] 3、...

    绿色perl使用说明

    perl5教程 包含: 变量,数组,文件读写,正则表达式,控制语句,哈希表,等常用perl的使用。

    PERL编程24学时教程

    15.4.2 在读写文件中移动 176 15.5 锁定文件 176 15.5.1 锁定UNIX和NT下的文件 178 15.5.2 在加锁情况下进行读写操作 179 15.5.3 Windows 95和Windows 98下的 加锁问题 180 15.5.4 在其他地方使用文件锁的问题 181 ...

    perl语言脚本文档说明

    15.4.2 在读写文件中移动 176 15.5 锁定文件 176 15.5.1 锁定UNIX和NT下的文件 178 15.5.2 在加锁情况下进行读写操作 179 15.5.3 Windows 95和Windows 98下的 加锁问题 180 15.5.4 在其他地方使用文件锁的问题 ...

    perl 程序开发教程

    第五章 文件读写 一、打开、关闭文件 二、读文件 三、写文件 四、判断文件状态 五、命令行参数 六、打开管道 第六章 模式匹配 一、简介 二、匹配操作符 三、模式中的特殊字符 1、字符 + 2、字符 []和[^] 3、...

    perl编程24学时教程.rar

    15.4.2 在读写文件中移动 176 15.5 锁定文件 176 15.5.1 锁定UNIX和NT下的文件 178 15.5.2 在加锁情况下进行读写操作 179 15.5.3 Windows 95和Windows 98下的 加锁问题 180 15.5.4 在其他地方使用文件锁的问题...

    Perl编程24学时教程(PDF格式,共24章)

    15.4.2 在读写文件中移动 176 15.5 锁定文件 176 15.5.1 锁定UNIX和NT下的文件 178 15.5.2 在加锁情况下进行读写操作 179 15.5.3 Windows 95和Windows 98下的 加锁问题 180 15.5.4 在其他地方使用文件锁的问题 181 ...

    Perl 语言入门 第六版

    以二进制方式读写文件句柄 有问题的文件句柄 关闭文件句柄 用die处理致命错误 用warn输出警告信息 自动检测致命错误 使用文件句柄 改变默认的文件输出句柄 重新打开标准文件句柄 用say来输出 …… 第六章...

    perl培训资料

    内容 一 概述 二 简单变量 ...文件读写 六 模式匹配 七 控制结构 八 子程序 九 关联数组(哈希表) 十 格式化输出 十一 文件系统 十二 Perl5中的引用(指针) 十三 Perl的面向对象编程 十四 Perl5的包和模块

    24日学好Perl语言

    15.4.2 在读写文件中移动 176 15.5 锁定文件 176 15.5.1 锁定UNIX和NT下的文件 178 15.5.2 在加锁情况下进行读写操作 179 15.5.3 Windows 95和Windows 98下的 加锁问题 180 15.5.4 在其他地方使用文件锁的问题 181 ...

Global site tag (gtag.js) - Google Analytics