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

Я открываю файл в режиме добавления. Мне нужно заменить строки 2,3 и 4 в файле, а позже мне нужно добавить новые данные в конец файла.

5 ответов


я думаю, что это ответ FAQ, который я перепостил в Stackoverflow больше всего. The 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;

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

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 $_;
    }

чтобы пропустить строки, используйте элементы управления циклами. Следующий в этом примере пропускает строки комментариев, а последний останавливает всю обработку, как только он встречает либо __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 для изменения файла на месте. Следующие изменения все 'Фред' to 'Barney' на inFile.txt, перезапись файла с новым содержимым. С -p переключатель, Perl оборачивает петлю времени вокруг код, который вы указываете с помощью -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

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


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

чтобы ответить на ваш вопрос, несколько строк кода (как можно более чистым) :

#!/usr/bin/env perl
use strict; use warnings;

while (<>) {
  if ($. == 2) {
    print "new data", "\n";
    next;
  }
  if ($. == 3) {
    print "very new data", "\n";
    next;
  }
  print;
}

print "more data", "\n"; 

тогда назовите это так: perl yourscript.pl inputfile > outputfile

Если вы хотите открыть файлы самостоятельно (Здесь мы просто пропустите ненужные строки):

my open $in_fh, '<', $inputfile
  or die "Can't open file $inputfile: $!";

my open $out_fh, '>', $outputfile
  or die "Can't open file $output: $!";

while (my $line = <$in_fh>) {
  next if ( $. == 2 or $. == 3 or $. == 4 );
  print $out_fh $line;
}
print $out_fh "...whatever\n";

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

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

думаю, я не совсем понимаю задание.


use File::Copy;

        copy("/file1.txt","/file1_old.txt");
        open(FILEHANDLE,">file1.txt");
        open(FILEHANDLE1,"<file1_old.txt");

        my $linecount=1;
        while(<FILEHANDLE1>)
        {
            print $_."\n";

            if($linecount>4)
            {
                print FILEHANDLE "$_";
            }
            $linecount++;
        }

        {
                ## new data will be placed
        }
        #####close the file handle
         close(FILEHANDLE1);
         close(FILEHANDLE);