如何使用Perl从文件中删除一行?

时间:2012-04-15 23:02:18

标签: 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

5 个答案:

答案 0 :(得分:13)

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

答案 1 :(得分:9)

Oalder的答案是correct,但他应该测试开放语句是否成功。如果文件times.txt不存在,您的程序将继续以愉快的方式继续,并且没有发出任何可怕的警告。

与oalders'相同的程序,但是:

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

    #!/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/>" ); 
    }
    

答案 2 :(得分:8)

看起来您正在打印到尚未定义的文件句柄。至少你没有在示例代码中定义它。如果启用严格和警告,您将收到以下消息:

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)除非您打算使用prototypes,否则您不需要子例程定义中的圆括号。请参阅上面的示例。

答案 3 :(得分:4)

答案 4 :(得分:0)

以防万一有人想从文件中删除所有行。

例如一个文件(第4行为空;第5行有3个空格):

t e st1
test2 a
  e

   
aa 
    bb bb
test3a
cc

要删除与某些人可能使用的模式匹配的行:

# Remove all lines with a character 'a'
perl -pi -e 's/.*a.*//' fileTest && sed -i '/^$/d' fileTest;

结果:

t e st1
  e
   
    bb bb
cc

相关:

perl -h
    # -p                assume loop like -n but print line also, like sed
    # -i[extension]     edit <> files in place (makes backup if extension supplied)
    # -e program        one line of program (several -e's allowed, omit programfile)

sed -h
    # -i[SUFFIX], --in-place[=SUFFIX]
    #                edit files in place (makes backup if SUFFIX supplied)

Reference 1Reference 2