Могу ли я использовать поиск и замену для вставки прогрессивного числа в Perl?

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

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

#!/usr/bin/perl
my $counter = 1;
my $oldID = "docID=\"";
my $newID = "docID=\"14$counter"; #should the return the IDs 141, 142, 143 ...

open (FILE, "file.txt") || die $!;
@content = <FILE>;

foreach (@content){
s/$oldID/$newID/;
$counter++;
}

open (OUT, ">file_ID.txt") || die $!;
print OUT @content;
close OUT;
close(FILE);

print = "$counter" #this is to test if the counter is working.

это находит и заменяет docID="". К сожалению, он заменяет все вхождения docID на 141.

Я бы предположил, что это не работает, потому что все вхождения заменяются сразу, и счетчик никогда не получает шанса увеличиться. Однако это не выглядит правдоподобным, если я вижу, что $counter становится слишком большим. Это ровно в 12 раз больше числа вхождений docID.

Я считаю, что мне нужно заставить perl заменить только одно вхождение docID, затем поднять счетчик, а затем сделать это в цикле до конца документа.

Может ли кто-нибудь помочь мне, пожалуйста? Я был бы очень признателен

Спасибо

Юлий


person Iulius    schedule 06.04.2011    source источник


Ответы (3)


open my $in, '<', 'file.txt' or die "$! opening input";
open my $out, '>', 'file_ID.txt' or die "$! opening output";

my $counter = 141;

while (<$in>) {
    s/docID="/q{docID="} . $counter++ /eg;
    print $out $_;
}

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

person hobbs    schedule 06.04.2011

Perl регулярные выражения поддерживают "eval", так что вы можете сделать:

s/$oldId/"docid=\"" . $newId++ . "\""/e

где /e — это eval часть, которая оценивает замену при каждом вызове.

person Wes Hardaker    schedule 06.04.2011

В своем коде вы можете переместить переменную $newID внутрь цикла for:

foreach (@content){
    my $newID = "docID=\"14$counter";
    s/$oldID/$newID/;
    $counter++;
}
person Shalini    schedule 06.04.2011