2014-02-09 3 views
2

Я был бы удивлен, если это не дубликат, но я не могу найти решение в любом месте для этой проблемы. Я пытаюсь заменить все экземпляры данной строки в файле другой строкой. Проблема, с которой я сталкиваюсь, заключается в том, что сценарий печатает замененную версию, но сохраняет оригинал. Я очень новой для PERL, так что я уверен, что это тривиальный вопрос, и я пропускаю что-тоPerl-файл regex не заменяет текст

Код:

my $count; 
my $fname = file_entered_by_user; 
open (my $fhandle, '+<', $fname) or die "Could not open '$fname' for read: $!"; 

for (<$fhandle>) { 
    $count += s/($item_old)/$item_new/g; 
    print $fhandle $_; 
} 
print "Replaced $count occurence(s) of '$item_old' with '$item_new'\n"; 
close $fhandle; 

Оригинал Файл:

This is test my test file where 
I test the string perl script with test 
strings. The word test appears alot in this file 
because it is a test file. 

Результаты поиска:

This is test my test file where 
I test the string perl script with test 
strings. The word test appears alot in this file 
because it is a test file 
This is sample my sample file where 
I sample the string perl script with sample 
strings. The word sample appears alot in this file 
because it is a sample file. 

Ожидаемый результат файла:

This is sample my sample file where 
I sample the string perl script with sample 
strings. The word sample appears alot in this file 
because it is a sample file. 

Дополнительная информация:

  • $item_old и $item_new предоставляются пользователем. В приведенных примерах я заменял test на sample.
  • Меня не интересует однострочное решение этой проблемы. Он должен быть интегрирован с более крупной программой, поэтому однострочные решения, которые могут запускаться с терминала, не будут слишком полезными.

ответ

4

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

Эта линия

for (<$fhandle>) { 

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

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

seek($fhandle, 0, 0); 

Хотя эти решения не очень хороши, на мой взгляд. Особенно, когда есть встроенные функции для обработки именно такого рода вещи:

perl -pi.bak -we 's/$item_old/$item_new/g' yourfile.txt 

-i флаг с -p флагом делает ваш код применяется в текстовый файл, и изменить его соответствующим образом, сохраняя копию с расширение .bak. Конечно, вы должны предоставить замену, которую хотите сделать, так как вы ее не предоставили.

Редактировать: Я только что увидел, что вы не хотите однострочный. Ну, чтобы сделать то, что делает этот однострочный лайнер, вам нужно только открыть правильные дескрипторы файлов и скопировать измененный файл поверх старого.Так, в основном:

use strict; 
use warnings; 
use File::Copy; 

open my $old, "<", $oldfile or die $!; 
open my $new, ">", $newfile or die $!; 

while (<$old>) { 
    s/$item_old/$item_new/g 
    print $new $_; 
} 
copy $newfile, $oldfile or die $!; 

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

+0

Спасибо, это разрешает мою проблему. – JamoBox

+0

Добро пожаловать. – TLP

Смежные вопросы