2014-02-10 5 views
0

Я работаю над скриптом, чтобы выполнить замену строки в файле, и я буду читать переменные и значения и файлы из файла конфигурации и выполнять замену строки.PERL: String Replacement в файле

Вот моя логика для замены строки.

sub expansion($$$){ 
my $f = shift(@_) ; # file Name 
my $vname = shift(@_) ; # variable name for pattern match 
my $value = shift(@_) ; # value to replace 
my $n = "$f".".new"; 

    open (O, "<$f") or print("Can't open $f file: $!"); 
    open (N ,">$n") or print("Can't open $n file: $!"); 
    while (<O>) 
    { 
     $_ =~ s/$vname/$value/g; #check for pattern 
     print N "$_" ; 
    } 
    close (O); 
    close (N); 


} 

В моей логике я строка за строкой считывания из входного файла ($ F) для рисунка и записи в новый файл ($ п).

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

+1

perl имеет встроенный 'exp'; выберите другое имя для своего юнита. также не используйте прототипы; они не предназначены для того, чтобы делать то, что делают прототипы на других языках, и вам лучше без них. – ysth

+0

Есть ли что-нибудь, что мешает вам копировать новый файл в старое имя файла? – TLP

+0

Я обновил имя функции, хотя в моем исходном сценарии я использовал другое имя ..thanks для указания. – Scg

ответ

0
sub inplace_expansion($$$){ 
    my $f = shift(@_) ; # file Name 
     my $vname = shift(@_) ; # variable name for pattern match 
     my $value = shift(@_) ; # value to replace 

    local @ARGV = ($f); 
    local $^I = ''; 
    while (<>) 
    { 
     s/\Q$vname/$value/g; #check for pattern 
     print; 
    } 
} 

или, мое предпочтение будет работать ближе к этому (в основном эквивалентны, изменяется в основном при форматировании, имена переменных и т.д.):

use English; 
sub inplace_expansion { 
    my ($filename, $pattern, $replacement) = @_; 
    local @ARGV = ($filename), 
     $INPLACE_EDIT = ''; 
    while (<>) { 
    s/\Q$pattern/$replacement/g; 
    print; 
    } 
} 

Трюк с local в основном имитирует сценарий командной строки (как можно было бы работать с perl -e); более подробно см. perldoc perlrun. Подробнее о $^I (aka $INPLACE_EDIT), см. perldoc perlvar.

(Для бизнеса с \Q (в выражении s//), см perldoc -f quotemeta. Это не имеет никакого отношения к вашему вопросу, но хорошо знать. Также следует помнить, что прохождение регулярных выражений шаблонов вокруг переменных — в отличие, например, с использованием буквальные регулярные выражения исключительно — могут быть уязвимы для атак инъекций, в Perl встроенного taint mode полезно здесь)

EDIT:. David W. является right о прототипах.

1

Нельзя. Никогда, никогда . Не смей, Даже не думай, не используйте прототипы подпрограммы. Он ужасно разбит (то есть, он не делает то, что, по вашему мнению, он делает) и равен dangerous.


Теперь мы получили, что из пути:

Да, вы можете делать то, что вы хотите. Вы можете open файл как для чтения, так и для записи с использованием режима <+. Все идет нормально.

Однако из-за буферизации вы не можете использовать стандартные методы чтения и записи для чтения и записи в файл. Вместо этого вам необходимо использовать sysread и syswrite.

Затем, вам необходимо прочитать строку , использовать sysseek, чтобы вернуться к началу того, где вы читаете, а затем пишите в это место.

Не только это очень сложно сделать, но оно полон опасности. Давайте рассмотрим простой пример. У меня есть документ, и я хочу заменить мои фигурные кавычки прямыми кавычками.

$line =~ s/“|”/"/g; 

Это должно сработать. Я заменяю одного персонажа другим. Что может пойти не так?

Если это файл UTF-8 (по умолчанию используются компьютеры Mac и Linux), эти фигурные кавычки являются двухбайтными символами и что прямая цитата является символом одного байта. Я бы напишет строку, которая была короче строки Я читал. Мой буфер отключен.

Назад в те дни, когда память и память компьютера были измерены в килобайтах, а у вас последовательные устройства, такие как ленты с катушками-катушками, этот тип работы был довольно распространенным. Тем не менее, в этом возрасте, где хранение является огромным, это просто не стоит сложность и склонность к ошибкам процесс, который это влечет за собой. Придерживайтесь чтения из одного файла и пишите другому. Затем используйте unlink и rename, чтобы удалить оригинал и переименовать копию под именем оригинала.

Еще несколько указателей:

  • Do не print, если файл не может быть открыт. Используйте die. В противном случае ваша программа будет просто продолжаться беспечно не осознавая, что она не работает. Еще лучше, используйте pragma use autodie;, и вам не придется беспокоиться о том, не удалось ли прочитать/записать.

  • Использование скаляров для ручек файлов.

То есть вместо

использования

open my $out_fh, ">my_file.txt"; 
  • И, настоятельно рекомендуется использовать параметр три разомкнут:

Использование

open my $out_fh, ">", "my_file.txt"; 
  • Если нет, всегда добавляют use strict; и use warnings;.

Фактически, ваш синтаксис Perl немного древний. Вам нужно получить книгу на Modern Perl. Первоначально Perl был написан как язык взлома для замены программ оболочки и awk. Однако Perl превратился в полноценный язык, способный обрабатывать сложные типы данных, ориентацию объектов и крупные проекты. Изучение современного синтаксиса Perl поможет вам найти ошибки и стать лучшим разработчиком.


1. Как и все правила, это может быть нарушена, но только если у вас есть четкое и тщательное понимание того, что происходит. Это похоже на те шоу, которые говорят «Не делай этого дома, мы профессионалы».