如何将文件内容读入Perl标量?

时间:2010-02-06 14:53:46

标签: html perl file slurp

我想要做的是从另一台服务器获取文件的内容。由于我与perl不一致,也不知道它的mod和函数,所以我就这样了:

 my $fileContents;
 if( $md5Con =~ m/\.php$/g ) {
     my $ftp = Net::FTP->new($DB_ftpserver, Debug => 0) or die "Cannot connect to some.host.name: $@";
     $ftp->login($DB_ftpuser, $DB_ftppass) or die "Cannot login ", $ftp->message;
     $ftp->get("/" . $root . $webpage, "c:/perlscripts/" . md5_hex($md5Con) . "-code.php") or die $ftp->message;
     open FILE, ">>c:/perlscripts/" . md5_hex($md5Con) . "-code.php" or die $!;
     $fileContents = <FILE>;
     close(FILE);
     unlink("c:/perlscripts/" . md5_hex($md5Con) . "-code.php");
     $ftp->quit;
 }

我认为id做的是从服务器获取文件,放在我的本地机器上,编辑内容,上传到任何地方然后删除临时文件。

但我似乎无法弄清楚如何获取文件的内容;

open FILE, ">>c:/perlscripts/" . md5_hex($md5Con) . "-code.php" or die $!;
$fileContents = <FILE>;
close(FILE);

不断出错;

使用未初始化的值$ fileContents

我猜这意味着它没有返回值。

任何帮助都非常感激。

&GT;&GT;&GT;&GT;&GT;&GT;&GT;&GT;&GT;&GT;编辑&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;

my $fileContents;
if( $md5Con =~ m/\.php$/g ) {
    my $ftp = Net::FTP->new($DB_ftpserver, Debug => 0) or die "Cannot connect to some.host.name: $@";
    $ftp->login($DB_ftpuser, $DB_ftppass) or die "Cannot login ", $ftp->message;
    $ftp->get("/" . $root . $webpage, "c:/perlscripts/" . md5_hex($md5Con) . "-code.php") or die $ftp->message;
    my $file = "c:/perlscripts/" . md5_hex($md5Con) . "-code.php";
    {
        local( $/ ); # undefine the record seperator
        open FILE, "<", $file or die "Cannot open:$!\n";
        my $fileContents = <FILE>;
        #print $fileContents;
        my $bodyContents;
        my $headContents;

        if( $fileContents =~ m/<\s*body[^>]*>.*$/gi ) {
            print $0 . $1 . "\n";
            $bodyContents = $dbh->quote($1);    
        }
        if( $fileContents =~ m/^.*<\/head>/gi ) {
            print $0 . $1 . "\n";
            $headContents = $dbh->quote($1);    
        }

        $bodyTable = $dbh->quote($bodyTable);
        $headerTable = $dbh->quote($headerTable);
        $dbh->do($createBodyTable) or die " error: Couldn't create body table: " . DBI->errstr;
        $dbh->do($createHeadTable) or die " error: Couldn't create header table: " . DBI->errstr;
        $dbh->do("INSERT INTO $headerTable ( headData, headDataOutput ) VALUES ( $headContents, $headContents )") or die " error: Couldn't connect to database: " . DBI->errstr;
        $dbh->do("INSERT INTO $bodyTable ( bodyData, bodyDataOutput ) VALUES ( $bodyContents, $bodyContents )") or die " error: Couldn't connect to database: " . DBI->errstr;
        $dbh->do("INSERT INTO page_names (linkFromRoot, linkTrue, page_name, table_name, navigation, location) VALUES ( $linkFromRoot, $linkTrue, $page_name, $table_name, $navigation, $location )") or die " error: Couldn't connect to database: " . DBI->errstr;

        unlink("c:/perlscripts/" . md5_hex($md5Con) . "-code.php");
    }
    $ftp->quit;
}

以上使用print WILL打印整个文件。但是,由于某种原因,两个正则表达式返回false。知道为什么吗?

if( $fileContents =~ m/<\s*body[^>]*>.*$/gi ) {
            print $0 . $1 . "\n";
            $bodyContents = $dbh->quote($1);    
        }
        if( $fileContents =~ m/^.*<\/head>/gi ) {
            print $0 . $1 . "\n";
            $headContents = $dbh->quote($1);    
        }

7 个答案:

答案 0 :(得分:10)

这是标准发行版中包含的covered in section 5 of the Perl FAQ

如何一次性读取整个文件?

您可以使用Path::Class::File::slurp模块一步完成。

use Path::Class;
$all_of_it = file($filename)->slurp; # entire file in scalar
@all_lines = file($filename)->slurp; # one line per element

处理文件中所有行的习惯Perl方法是一次一行:

open (INPUT, $file) || die "can't open $file: $!";
while (<INPUT>) {
    chomp;
    # do something with $_
}
close(INPUT)        || die "can't close $file: $!";

这比将整个文件作为行数组读入内存然后一次处理一个元素要高效得多,这通常是 - 如果不是总是 - 错误的方法。每当你看到有人这样做时:

@lines = <INPUT>;

你应该长时间地思考为什么你需要一次装满所有东西。这不是一个可扩展的解决方案。您可能还会发现使用标准Tie::File模块或DB_File模块的$DB_RECNO绑定更有趣,它允许您将数组绑定到文件,以便访问数组元素实际上访问文件中的相应行。

您可以将整个文件句柄内容读入标量。

{
local(*INPUT, $/);
open (INPUT, $file) || die "can't open $file: $!";
$var = <INPUT>;
}

暂时取消您的记录分隔符,并在块退出时自动关闭该文件。如果文件已经打开,请使用:

$var = do { local $/; <INPUT> };

对于普通文件,您还可以使用read功能。

read( INPUT, $var, -s INPUT );

第三个参数测试INPUT文件句柄上数据的字节大小,并将那么多字节读入缓冲区$var

答案 1 :(得分:8)

如果您想一次性阅读所有文件内容,请使用Path::Class::File::slurp

但更重要的是,使用HTML parser来解析HTML。

答案 2 :(得分:3)

open FILE, "c:/perlscripts" . md5_hex($md5Con) . "-code.php" or die $!;
while (<FILE>) {
    # each line is in $_
}
close(FILE);

将打开该文件并允许您逐行处理(如果这是您想要的 - 否则调查binmode)。我认为问题在于您在使用>>打开文件名前。有关详细信息,请参阅this tutorial

我注意到你也使用正则表达式来解析HTML。通常我建议使用解析器来执行此操作(例如,请参阅HTML::Parser)。由于HTML缺乏规律性,正则表达式不适合HTML,并且在一般情况下不能可靠地工作。

答案 3 :(得分:2)

此外,如果您需要编辑文件的内容,请查看CPAN模块 Tie::File
此模块使您无需创建用于编辑内容的临时文件 并将其写回同一个文件。

修改的:
你在看什么是一种诽谤文件的方法。也许你必须取消定义 记录分隔符变量$/

以下代码适用于我:

use strict;
my $file = "test.txt";
{
    local( $/ ); # undefine the record seperator
    open FILE, "<", $file or die "Cannot open:$!\n";
    my $lines =<FILE>;
    print $lines;
}

use strict; my $file = "test.txt"; { local( $/ ); # undefine the record seperator open FILE, "<", $file or die "Cannot open:$!\n"; my $lines =<FILE>; print $lines; } 另请参阅此article中的“传统啜食”部分。

答案 4 :(得分:1)

  

但是,由于某种原因,两个正则表达式返回false。知道为什么吗?

默认情况下,正则表达式中的

.匹配除换行符之外的任何字符 。假设您在</head>代码之前和<body>代码之后有换行符。要使.与任何字符(包括换行符)匹配,请使用//s标记。

我不确定你的print $0 . $1 ...代码是什么;你没有在你的比赛中捕获任何存储在$ 1中的东西,$ 0不是用于正则表达式捕获的变量,它是非常不同的。

答案 5 :(得分:0)

如果你想获取文件的内容,

 @lines = <FILE>;

答案 6 :(得分:0)

使用File::Slurp::Tiny。和File::Slurp一样方便,但没有bugs