2009-06-02 2 views
0

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

#!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; 

ответ

5

Ваш 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"; 

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

1

открыта для записи = «>» открыта для чтения = «<»

7

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

Кроме того, вы не можете иметь регулярное выражение в шаблоне замещения $replace.

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

perl -pi -e 's/(\s{6}seqfile\s=\sinfil)e/${1}2/' /home/shubhi/Desktop/pamlrun/test 
4

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

#!/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 
+0

Я нахожу Tie :: Файл проще. – Svante