Как изменить, удалить или вставить строку в файл, или добавить в начало файла в Perl?

люди продолжают задавать этот вопрос, и я продолжаю отвечать на него тем же ответом от perlfaq5. Теперь это то, на что мы можем указать на Stackoverflow.

1 ответов


С perlfaq5:

основная идея вставки, изменения или удаления строки из текстового файла включает в себя чтение и печать файла до точки, в которую вы хотите внести изменения, внесение изменений, а затем чтение и печать остальной части файла. Perl не обеспечивает произвольный доступ к строкам (особенно с разделителем ввода записи,$/, является изменяемым), хотя такие модули, как Tie:: File фейк это.

На Perl программа для выполнения этих задач принимает основную форму-открытие файла, печать его строк, затем закрытие файла:

open my $in,  '<',  $file      or die "Can't read old file: $!";
open my $out, '>', "$file.new" or die "Can't write new file: $!";

while( <$in> )
    {
    print $out $_;
    }

close $out;

в этой базовой форме добавьте детали, которые необходимо вставить, изменить или удалить строки.

чтобы добавить строки в начало, распечатайте эти строки перед вводом цикла, который печатает существующие строки.

open my $in,  '<',  $file      or die "Can't read old file: $!";
open my $out, '>', "$file.new" or die "Can't write new file: $!";

print $out "# Add this line to the top\n"; # <--- HERE'S THE MAGIC

while( <$in> )
    {
    print $out $_;
    }

close $out;

чтобы изменить существующие строки, вставьте код для изменения строк внутри while петли. В этом случае код находит все строчные версии "perl" и прописные буквы. Это происходит для каждой строки, поэтому убедитесь, что вы должны делать это на каждой строке!

open my $in,  '<',  $file      or die "Can't read old file: $!";
open my $out, '>', "$file.new" or die "Can't write new file: $!";

print $out "# Add this line to the top\n";

while( <$in> )
    {
    s/\b(perl)\b/Perl/g;
    print $out $_;
    }

close $out;

чтобы изменить только определенную строку, Номер входной строки,$., это полезно. Сначала прочитайте и распечатайте строки до той, которую вы хотите изменить. Затем прочитайте одну строку, которую вы хотите изменить, измените ее и распечатайте. После этого прочитайте остальные строки и распечатайте их:

while( <$in> )   # print the lines before the change
    {
    print $out $_;
    last if $. == 4; # line number before change
    }

my $line = <$in>;
$line =~ s/\b(perl)\b/Perl/g;
print $out $line;

while( <$in> )   # print the rest of the lines
    {
    print $out $_;
    }

чтобы пропустить строки, используйте управление циклом. The next в этом примере пропускает строки комментариев и last останавливает всю обработку как только он сталкивается либо __END__ или __DATA__.

while( <$in> )
    {
    next if /^\s+#/;             # skip comment lines
    last if /^__(END|DATA)__$/;  # stop at end of code marker
    print $out $_;
    }

сделайте то же самое, чтобы удалить определенную строку с помощью next, чтобы пропустить строки, которые вы не хотите показывать в выходные. Этот пример пропускает каждую пятую строку:

while( <$in> )
    {
    next unless $. % 5;
    print $out $_;
    }

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

open my $in,  '<',  $file      or die "Can't read old file: $!"
open my $out, '>', "$file.new" or die "Can't write new file: $!";

my @lines = do { local $/; <$in> }; # slurp!

    # do your magic here

print $out @lines;

модули, такие как File:: Slurp и Tie:: File может помочь с этим тоже. Если вы можете, однако, избежать чтения всего файла сразу. Perl не вернет эту память операционной системе до завершения процесса.

вы также можете использовать Perl one-liners для изменения файла на месте. Следующие изменения все "Фред" на "Барни" в inFile.txt, переписывая файл с новым содержимым. С -p переключатель, Perl обертывает while петли вокруг кода, который вы указываете с -e и -i включает редактирование на месте. Текущая строка находится в $_. С -p, Perl автоматически печатает значение $_ в конце цикла. См.perlrun для более подробной информации.

perl -pi -e 's/Fred/Barney/' inFile.txt

сделать резервную копию inFile.txt, дать -i расширение файла, чтобы добавить:

perl -pi.bak -e 's/Fred/Barney/' inFile.txt

изменить только пятую строку, вы можете добавить тестовую проверку $., номер строки входного сигнала, после этого только выполняет деятельность когда тест проходит:

perl -pi -e 's/Fred/Barney/ if $. == 5' inFile.txt

чтобы добавить строки перед определенной строкой, вы можете добавить строку (или строки!) до Perl выводит $_:

perl -pi -e 'print "Put before third line\n" if $. == 3' inFile.txt

вы даже можете добавить строку в начало файла, так как текущая строка печатается в конце цикла:

perl -pi -e 'print "Put before first line\n" if $. == 1' inFile.txt

чтобы вставить строку после одной уже в файле, используйте -n переключатель. Это как ... -p кроме того, что он не печатает $_ в конце цикла, так что вы должны сделать это сами. В этом случае print $_ во-первых, затем распечатать строку, которую вы хотите добавить.

perl -ni -e 'print; print "Put after fifth line\n" if $. == 5' inFile.txt

удалить строки, печатать только те, которые вы хотите.

perl -ni -e 'print unless /d/' inFile.txt

    ... or ...

perl -pi -e 'next unless /d/' inFile.txt