2012-04-15 2 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

+0

@geekosaur Я ничего не получаю от предупреждений .. – varatis

+1

Тогда ваш выход идет куда-то, кроме того, где он должен быть. Проверьте, где вы его пишете. – geekosaur

ответ

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) Ваш пример кода вызывает removeReservation(), когда вы имеете в виду removeTime()

2) Вам не нужны круглые скобки в определении подпрограммы, если вы не намерены использовать prototypes. См. Мой пример выше.

+0

Спасибо за эту концепцию, я изо всех сил пытался читать и обновлять строку в одном дескрипторе файла! – a7omiton

5

Ответ Оальдера 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 open и проверка на то, что открытые прецеденты являются ключевыми, если вы действительно хотите очистить вещи. Использование autodie и/File :: Slurp действительно может сократить код, но это гораздо более тщательный ответ, чем мой собственный. – oalders

10
perl -ni -e 'print unless /whatever/' filename 
Смежные вопросы