Как я заменяю строки посреди файла с Perl?

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

19
задан brian d foy 22 February 2010 в 00:19
поделиться

5 ответов

Думаю, это ответ на часто задаваемый вопрос, который я чаще всего отправлял в 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'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 $_;
    }

Чтобы пропустить строки, используйте элементы управления циклом. Следующий в этом примере пропускает строки комментариев, а последний останавливает всю обработку при обнаружении либо __ 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 для изменения файла на месте. Следующее изменяет все «Фред» на «Барни» в 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
41
ответ дан 30 November 2019 в 02:56
поделиться

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

4
ответ дан 30 November 2019 в 02:56
поделиться
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);
-3
ответ дан 30 November 2019 в 02:56
поделиться

Хорошая идиома Perl - читать и записывать стандартный ввод и вывод. При необходимости вы можете перенаправить и перенаправить. С помощью оператора <> (перенос в строку чтения) 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";
3
ответ дан 30 November 2019 в 02:56
поделиться

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

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

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

0
ответ дан 30 November 2019 в 02:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: