LINUX.ORG.RU

Не получается перезаписать файл в Perl

 


1

1

Помогите пожалуйста. Начала осваивать Perl, написала программку и что-то не так. Смысл был в том, чтобы при помощи регулярных выражений is поменять на at и перезаписать исходный файл с полученным результатом. Файл вообще не переписывается, а всё напрочь стирается. Подскажите, где что не так.

#!/usr/bin/perl -w

use diagnostics;
use warnings;
use strict;

open (FILE, '>>apple.txt');
while (<FILE>){      
s/is/at/;                      # Substitute 'is' for 'at'
print FILE;
close (FILE);   
}

Для одновременного чтения и записи режим открытия «>+», а не «>>». Закрывать файл нужно после цикла, а не каждый раз. Ну и ещё, видимо, понадобится функция seek().

Olegymous ★★ ()

Мой вариант:

open my $fh, '+>>', 'apple.txt';
while (my $line = <$fh>) {
    $line =~ s{is}{at};
    print {$fh} $line;
}
close $fh;

«close» надо вынести из блока while, ему там не место. Чтобы прервать выполнение while, надо использовать функции last/next (https://perldoc.perl.org/functions/last.html).

И еще модификатор доступа поменять: «You can put a + in front of the > or < to indicate that you want both read and write access to the file».

И видимо надо запоминать позицию которую прочитали из файла. Просто check and set не сработает.

outtaspace ★★★ ()
Последнее исправление: outtaspace (всего исправлений: 1)

Учтите, что без фокусов с -i/$^I строки изменять получится, только сохраняя их длину. Как только это не удастся гарантировать, придётся создавать временный файл, писать результаты изменения в него, а потом дёргать rename, чтобы перезаписать новым файлом старый.

anonymous ()
Ответ на: комментарий от anonymous

А так, если длинным способом, надо бы в временный файл писать:


use strict;
use warnings;

use File::Copy;

my $changeFileName = 'test.txt';
my $tmpFileName = "/tmp/$changeFileName.tmp";

open my $changeHandle, '<', $changeFileName;
open my $tmpHandle, '>', $tmpFileName;

while (<$changeHandle>) {
    s/is/at/g;
    print $tmpHandle $_;
}

close $changeHandle;
close $tmpHandle;

move($tmpFileName, $changeFileName);
anonymous ()
Ответ на: комментарий от theNamelessOne

my

Какая пошлятина этот ваш Perl.

anonymous ()
Ответ на: комментарий от theNamelessOne

Зато целый символ сэкономил! :) Да, глуповато с моей стороны - слишком мало думал, пока писал. Тут вообще-то, несколько и более серьёзных недочётов - не проверяю возврат из функции (вдруг ошибка чтения/записи?), создание временного файла через задницу - надо бы использовать File::Temp, никуда не годится конструкция «/tmp/$changeFileName.tmp» - вдруг в $changeFileName не только имя файла, но и путь к нему. В общем, на работе я так не пишу. :)

anonymous ()

Если файлы не предполагаются больших размеров, то лучше считать целиком в память, а затем так же целиком записать.

Если же предполагаются, то надо писать в другой файл, а не в этот же, поскольку в общем случае замена может менять длину заменяемого куска. После создания нового файла, нужно переименовать его в старый, получится как бы то что надо.

Casus ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.