Подтвердить что ты не робот

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

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

4b9b3361

Ответ 1

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

Чтобы пропустить строки, используйте элементы управления циклом. Следующий в этом примере пропускает строки комментариев, а последний останавливает всю обработку после того, как он встретит либо __END__, либо __DATA__.

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

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

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 для изменения файла на месте. Следующее изменяет все "Fred" на "Barney" в 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, за исключением того, что он не печатает $_ в конце цикла, поэтому вам нужно это сделать самостоятельно. В этом случае сначала напечатайте $_, затем напечатайте строку, которую вы хотите добавить.

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

Ответ 2

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

Ответ 3

Хорошая 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";

Ответ 4

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

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

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

Ответ 5

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);