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

var*_*tis 5 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/>");
}
Run Code Online (Sandbox Code Playgroud)

示例times.txt文件:

04/15/2012&08:00:00&bob
04/15/2012&08:00:00&john
Run Code Online (Sandbox Code Playgroud)

Dan*_*ral 14

perl -ni -e 'print unless /whatever/' filename
Run Code Online (Sandbox Code Playgroud)

  • 或者相反:`perl -pi -e's /.* whatever。* //'filename` (2认同)
  • @r_2 这会删除该行,还是只是将其清空?我期望后一种行为。 (2认同)

Dav*_* W. 9

奥尔德的答案是正确的,但他应该测试开放的陈述是否成功.如果该文件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/>" ); 
}
Run Code Online (Sandbox Code Playgroud)


oal*_*ers 8

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

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

print NEWLIST $LINE unless ($LINE =~ m/$name/);
Run Code Online (Sandbox Code Playgroud)

此代码应该适合您:

#!/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/>" ); 
}
Run Code Online (Sandbox Code Playgroud)

还有几点需要注意:

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

2)除非您打算使用原型,否则在子例程定义中不需要圆括号.见上面的例子.