Почему мой Perl-скрипт удаляет содержимое всего файла, когда я пытаюсь редактировать файл? - PullRequest
0 голосов
/ 02 июня 2009

Я запускаю следующий код, чтобы открыть файл (проверить) и отредактировать (найти и заменить) его. Программа, кажется, открывает файл, но вместо замены удаляет все в файле. Я не уверен, почему это происходит. Может кто-нибудь помочь мне здесь?

#!use/bin/perl
use strict;
use warnings;

my $line = $ARGV[0];
my $find = '\s{6}seqfile\s=\sinfile';
my $replace = '\s{6}seqfile\s=\sinfil2';

open (FILE, ">/home/shubhi/Desktop/pamlrun/test") || die "cant open file \n";
my @body = <FILE>;
foreach $line(@body)
{
(s/$find/$replace/g);
{
print FILE "$line";
}
}
close(FILE);
print "reached here\n";
exit;

Ответы [ 4 ]

7 голосов
/ 02 июня 2009

open(FILE, ">filename") открывает файл в режиме замены, записывая поверх того, что было ранее.

Кроме того, вы не можете иметь регулярное выражение в шаблоне подстановки $replace.

Если я правильно понял ваше намерение, его можно заменить однострочным

perl -pi -e 's/(\s{6}seqfile\s=\sinfil)e/${1}2/' /home/shubhi/Desktop/pamlrun/test
5 голосов
/ 02 июня 2009

Ваш open () открывает дескриптор файла для записи в ваш файл. Заменить

open (FILE, ">/home/shubhi/Desktop/pamlrun/test") || die "cant open file \n";

с

open (FILE, "/home/shubhi/Desktop/pamlrun/test") || die "cant open file \n";

В опубликованном вами коде он сразу создает этот файл только для вывода. Вы должны открыть файл, прочитать / обработать содержимое, а затем записать его. Если размер файла достаточно велик, запишите в новый файл, когда вы читаете старый, и замените старый после (успешного) завершения.

4 голосов
/ 02 июня 2009

Похоже, вы хотите волшебство редактирования на месте. Самый простой способ получить это - использовать $^I с магией @ARGV плюс <> (ищите нулевой дескриптор файла в разделе Операторы ввода / вывода ):

#!/usr/bin/perl

use strict;
use warnings;

my $find = qr/\s{6}seqfile\s=\sinfile/;
my $replace = '      seqfile = infil2';

@ARGV = ("/home/shubhi/Desktop/pamlrun/test");

$^I = ".bak"; #safe the old files as file.bak

while (<>) {
    s/$find/$replace/g;
    print;
}

Кроме того, учитывая природу вашего регулярного выражения, похоже, что вы, вероятно, хотите [ ] (соответствует пробелу) или \t (соответствует символу табуляции), а не \s. \s будет соответствовать символам табуляции, пробелов и других пробельных символов.

Вы также можете использовать Tie::File, но, похоже, он не обеспечивает возможности резервного копирования:

#!/usr/bin/perl

use strict;
use warnings;

use Tie::File;

my $find = qr/\s{6}seqfile\s=\sinfile/;
my $replace = '      seqfile = infil2';

tie my @lines, "Tie::File", "testdata"
    or die "could not open file: $!";

for my $line (@lines) {
    $line =~ s/$find/$replace/g;
}

Конечно, вы можете свернуть свои собственные резервные копии с File::Copy:

#!/usr/bin/perl

use strict;
use warnings;

use Tie::File;
use File::Copy;

my $find = qr/\s{6}seqfile\s=\sinfile/;
my $replace = '      seqfile = infil2';

copy "testdata", "testdata.bak"
    or die "could not backup file: $!";

tie my @lines, "Tie::File", "testdata"
    or die "could not open file: $!";

for my $line (@lines) {
    $line =~ s/$find/$replace/g;
}

Я также был бы упущен, если бы не указал, что это в основном однострочный текст:

perl -pi.bak -e 's/\s{6}seqfile\s=\sinfile/      seqfile = infil2/' testdata

Это можно еще больше сократить с помощью Perl 5.10, воспользовавшись преимуществом \K (позитивный обзор нулевой ширины):

perl -pi.bak -e 's/\s{6}seqfile\s=\s\Kinfile/infil2/' testdata
1 голос
/ 02 июня 2009

открыто для записи = '>' открыть для чтения = '<' </p>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...