【问题标题】:Using Perl to open a file and preview its contents使用 Perl 打开文件并预览其内容
【发布时间】:2015-09-21 14:22:12
【问题描述】:

我正在为学校做一个项目,这门课非常不具描述性。我不明白发生了什么以及为什么我无法显示文件。

#!/usr/bin/perl

use 5.010;
use strict;
use warnings;

print "\n+--------------------------+";
print "\n| The File Search &        |";
print "\n|         Display Tool     |";
print "\n+--------------------------+";

print "\nPlease enter the file you would like to read (with full path): \n";

my $FILE = <STDIN>;
chomp $FILE;
sleep 1;

open (FILE, "$FILE");
print "  Here is the secret information you seek supreme leader: \n";
print "==============================================================";

while ($FILE) {
    chomp $FILE;
    open $FILE;
}

我不完全确定我做错了什么。我尝试了各种不同的组合,但它只会导致错误。


更新

所以我根据大家的建议对代码进行了一些修改(见下文)。运行脚本后返回以下错误

readline() on unopened filehandle at test.pl line 30.

在下面的代码中,我想我打开了文件句柄,但这个错误让我觉得我在打开命令附近的某个地方搞砸了。

#!/usr/bin/perl

use 5.010;
use strict;
use warnings;

print "\n+--------------------------+";
print "\n| The File Search &        |"; #Not so fancy banner! 
print "\n|         Display Tool     |"; 
print "\n+--------------------------+";

print "\n   Welcome to the Tool. It is still being tested!!\n";
print "\n    Please enter the file you would like to read: ";

my $filename = <STDIN>; #define the variable for the filename

if ( not -f $filename ) #This checks the validity of the file
{
print "Filename does not exist\n";
exit;
}

sleep 1;

print "  Here is the secret information you seek supreme leader: \n";
print "==============================================================\n";

open my $filehandle, "<", $filename; #or die $!

while ( <$filename> ) { #While loop to read each line of the file
    chomp;
    print "$_\n";
}

我注释掉了打开字符串的 or die 部分,因为它只是杀死了脚本,我想看看有什么问题。我对 open 语句中的“

【问题讨论】:

  • 我只能说 - 通常家庭作业问题意味着不好的问题。这实际上是一个很好的问题,而且很明确且可以回答。
  • @Borodin 对这个错误有什么建议吗?
  • 您应该真正打开一个新问题,而不是更新现有问题——Stack Overflow 与论坛非常不同。这里有两个问题。如果or die 正在杀死脚本,那么这意味着打开由于某种原因而失败,并且尝试从句柄中读取是没有意义的。其次,您有&lt;$filename&gt;,这是对原始代码的回归:您无法从文件名中读取!我还建议使用$fh 而不是$filehandle,因为后者在视觉上与$filename 没有太大区别
  • 可能不清楚的地方 -- &lt;$fh&gt; 是文件句柄上的 readline $fh
  • open 调用有一个、两个和三个参数形式。第一个非常古老,最好被遗忘。第二个大概是你熟悉的,打开模式与文件名混在一起,你写open my $fh, '&lt;myfile.txt',你可以省略&lt;作为读取模式。这仍然是一个小技巧,最后一种形式现在被认为是最佳实践,其中每条输入都是分开的。这意味着您可以打开名称为 &lt; 的文件,这些文件在 Linux 平台上有效,但无法以任何其他方式打开

标签: perl


【解决方案1】:

你只是把你的变量搞混了。您正在使用$FILEFILE,以及(不可见的)$_$FILE 以文件的 name 开头,但您也从中读取,chomp 它和 open 它是错误的

您应该open 文件名、读取 文件句柄和print 您已读取的内容(或任何其他值)。最好对所有局部变量使用小写,为全局变量保留大写

您的代码应如下所示。我使用了 lexical 文件句柄 $fh 而不是老式的全局句柄。将变量放在 "$FILE" 这样的引号中是错误的:充其量没有区别,但它可能会破坏您的程序。此外,&lt;$fh&gt; 在类似的while 循环中读入默认变量$_,这也是chomp 的默认参数。把它想象成英语中的代词it

open my $fh, '<', $file_name;
while ( <$fh> ) {
    chomp;
    print "$_\n";
}

【讨论】:

  • 有效使用隐式变量是perl 的一项重要技能。你摸索了一下,你可以编写一些可爱的代码,但在你写完之前,还有许多陷阱等待着你!
  • 你的 cmets 肯定已经让我知道我做错了什么。教授刚发了作业,我一个人。在这种情况下使用全局文件句柄和词法文件句柄的解释更有意义;因为我刚刚做了一些研究,为什么它们在某些事情上比全局变量更好。有一个知道自己在做什么的人愿意像你一样帮助和解释事情,这绝对是有帮助的。我假设一旦定义了全局变量,就必须遵循它。我现在绝对可以看到我的错误是基于此的。
  • @undecisive:找到一个愿意学习的学生真是令人鼓舞!你说的我一个人是什么意思?词法文件和目录句柄相对于全局句柄的最大优势首先与 any 局部标识符相对于全局标识符的优势相同——您可以避免访问和修改错误的变量。在 Perl 的情况下,您还有一个优势,即句柄在超出范围时将被关闭,从而使您无需编写内务代码
  • @Borodin 基本上老师给了我们一个非常简短的perl概述以及如何写hello world,然后教我们如何使用chop和chomp来删除字符。下一项现在是编写脚本来打开文件并读取其中的内容。因此,我一直在测试和尝试脚本中的不同内容,以查看是否可以打开它,甚至尝试使用 File::Find 之类的东西来定位文件。在这一点上这还远远不够,我肯定会在尝试添加模块之前尝试更好地掌握词汇文件句柄并使用“基本”命令。
  • @Borodin 所以从本质上讲,这是向 perl 的巨大飞跃,指令非常少。所以我整个星期都在尝试这个和谷歌搜索;无济于事,因为我并不真正了解自己在寻找什么,最后决定我需要一些更有经验的人的帮助,而且我最近使用 stackoverflow 解决 python 问题。
【解决方案2】:

这里的核心问题是你重新打开,而不是真正阅读。

打开文件:

open ( my $filehandle, "<", $filename ) or die $!;

die 非常重要,因为它会告诉您打开文件是否有问题。 $! 是打开操作的“状态码”,如果找不到文件,它会告诉你。

所有这样做是“设置”$filehandle 为您提供访问点。

要获取文件的内容,您需要读取它,在perl 中,这是通过&lt;&gt; 完成的。

所以:

my $line = <$filehandle>

将读取一行。

如果您想读取多行内容,请在 while 循环中执行。

while ( my $line = <$filehandle> ) {
    print $line;
}

您可能还会发现在执行此操作之前测试文件是否存在很有用:

if ( not -f $filename ) { 
   print "$filename does not exist\n";
   exit; 
}

【讨论】:

  • Sobrique,这与@Borodin 所说的相似。我喜欢先测试文件是否存在的想法,以便在文件不存在的情况下为程序提供退出点。我想知道鲍罗丁的剧本中的“”做了什么,正要参考它,但你已经把它拼出来了。你们对这里的超级新 perl 用户非常有帮助;甚至比我的教授还要多,我将尝试使用大家提到的项目,例如词法文件句柄和读取参数,以尝试更好地理解这些基本的 perl 函数。
  • 我们都是从头开始的。不断提出好的问题,你会从这个网站学到很多东西。
  • 同意。我们都从新手开始,但最终获得了成功完成任务的知识。我只是希望我能在 perl 和 python 方面有所了解,并将一些知识传递给将来对这两者都不熟悉的人。
【解决方案3】:

两个问题:第一,您从 FILE 读取的方式与从 STDIN 读取的方式相同,使用 &lt;&gt; 运算符。二、假设你想显示$FILE的内容,你的while循环应该是这样的

while (<FILE>) {
    print;
}

这使用隐式变量$_ 存储每次通过循环从FILE 读取的行,这与print 使用的变量相同,没有其他参数。更明确地说,你可以写

while (my $line = <FILE>) {
    print "$line";
}

chomp 不需要,因为print 不会打印额外的换行符,除非你告诉它。你也可以写

while (<FILE>) {
    chomp;
    print "$_\n";
}

while (my $line = <FILE>) {
    chomp $line;
    print "$line\n"
}

【讨论】:

  • 我建议重命名文件名 ($FILE) 或文件句柄 (FILE) 之一,因为这只会造成混淆。
  • 同意;我通常使用FH 作为文件句柄,$fname 作为文件名。
  • @chepner:您还应该使用词法文件句柄 -- $fh 而不是 FH
  • 切普纳感谢您的建议。我想我想做的是你最后一个例子,然后打印出来。显然我做错了,但是嘿,我正在学习,你们都很好,可以为我一步一步地分解它。吉姆,您的建议已被注意到,我将避免使用大写字母作为变量名,并为文件句柄保留大写字母。 (我认为这就是你所说的)
  • 我确实使用了词法文件句柄,但似乎我在答案中堆积了足够多的新概念。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-21
  • 1970-01-01
  • 2013-07-13
相关资源
最近更新 更多