2012-04-15 170 views
4

我试图从文本文件中删除一行。相反,我已经清除了整个文件。有人可以指出错误吗?如何使用Perl从文件中删除一行?

removeReservation("john"); 

sub removeTime() { 
    my $name = shift; 

    open(FILE, "<times.txt"); 
    @LINES = <FILE>; 
    close(FILE); 
    open(FILE, ">times.txt"); 
    foreach $LINE (@LINES) { 
     print NEWLIST $LINE unless ($LINE =~ m/$name/); 
    } 
    close(FILE); 
    print("Reservation successfully removed.<br/>"); 
} 

样品times.txt文件:

04/15/2012&08:00:00&bob 
04/15/2012&08:00:00&john 
+0

始终'使用警告;'。 – geekosaur 2012-04-15 23:03:22

+0

@geekosaur我没有从警告中得到任何东西。 – varatis 2012-04-15 23:09:38

+1

然后,你的输出将在某处,而不是它应该在的地方。检查你写的地方。 – geekosaur 2012-04-15 23:11:53

回答

7

它看起来像你打印到您还没有定义的文件句柄。至少你还没有在你的示例代码中定义它。如果启用了严格和警告,你会得到以下信息:

Name "main::NEWLIST" used only once: possible typo at remove.pl line 16. 

print NEWLIST $LINE unless ($LINE =~ m/$name/); 

此代码应为你工作:

#!/usr/bin/env perl 

use strict; 
use warnings; 

removeTime("john"); 

sub removeTime { 
    my $name = shift; 

    open(FILE, "<times.txt"); 
    my @LINES = <FILE>; 
    close(FILE); 
    open(FILE, ">times.txt"); 
    foreach my $LINE (@LINES) { 
     print FILE $LINE unless ($LINE =~ m/$name/); 
    } 
    close(FILE); 
    print("Reservation successfully removed.<br/>"); 
} 

一对夫妇的其他注意事项:

1)您的示例代码在您的意思是removeTime()时调用removeReservation()

2)除非您的意图是使用,否则在子例程定义中不需要圆括号。看我上面的例子。

+0

感谢这个概念,我一直努力在一个文件句柄中读取和更新行! – a7omiton 2014-08-19 22:23:00

5

Oalder的回答是correct,但他应该已经测试过的打开语句是否成功。如果文件times.txt不存在,您的程序将继续其快乐的方式,没有任何警告,说有什么可怕的事情发生。

相同的节目oalders'但:

  1. 测试的open的结果。
  2. 使用三个部分公开声明这是更穿帮证明。如果您的文件名以>|开头,则您的程序将以旧的两部分语法失败。
  3. 不使用全局文件句柄 - 尤其是在子例程中。文件句柄通常在全局范围内。想象一下,如果我在我的主程序中有一个名为FILE的文件句柄,并且正在读它,我就调用了这个子例程。那会造成问题。使用本地作用域文件句柄名称。
  4. 变量名应该小写。常量都是大写的。这只是一个随着时间的推移而发展的标准。不遵循它可能会导致混淆。
  5. 由于oalders把程序放在一个子程序,你应该通过在子程序以及文件的名称...

这里的程序:

#!/usr/bin/env perl 

use strict; 
use warnings; 

removeTime("john", "times.txt"); 

sub removeTime { 
    my $name  = shift; 
    my $time_file = shift; 

    if (not defined $time_file) { 
     #Make sure that the $time_file was passed in too. 
     die qq(Name of Time file not passed to subroutine "removeTime"\n); 
    } 

    # Read file into an array for processing 
    open(my $read_fh, "<", $time_file) 
     or die qq(Can't open file "$time_file" for reading: $!\n); 

    my @file_lines = <$read_fh>; 
    close($read_fh); 

    # Rewrite file with the line removed 
    open(my $write_fh, ">", $time_file) 
     or die qq(Can't open file "$time_file" for writing: $!\n); 

    foreach my $line (@file_lines) { 
     print {$write_fh} $line unless ($line =~ /$name/); 
    } 
    close($write_fh); 

    print("Reservation successfully removed.<br/>"); 
} 
+0

这在文体上比我的答案更好。 IIRC我只是改变了代码的最小数量来得到这个例子的工作,但是3 arg打开并且检查打开成功是否关键,如果你真的想要清理的话。使用autodie和/或File :: Slurp也可以真正减少代码,但这是比我自己更彻底的回应。 – oalders 2013-11-27 06:01:02

10
perl -ni -e 'print unless /whatever/' filename