В Perl как изменить, удалить или вставить строку в файл или добавить в начало файла? - PullRequest
27 голосов
/ 08 декабря 2010

Я хочу внести изменения в содержимое файла, изменив, удалив или вставив строки или добавив в начало файла.Как я могу это сделать в Perl?


Это вопрос из официального FAQ .Мы импортируем perlfaq в Stack Overflow .

1 Ответ

42 голосов
/ 08 декабря 2010

(Это официальный ответ perlfaq , за вычетом любых последующих правок)

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

AПрограмма 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 для изменения файла на месте.Следующее меняет все 'Fred' на 'Barney' в inFile.txt, перезаписывая файл новым содержимым.С переключателем -p Perl оборачивает цикл while вокруг кода, который вы указали с помощью -e, а -i включает редактирование на месте.Текущая строка в $_.При -p Perl автоматически печатает значение $_ в конце цикла.См. perlrun для получения более подробной информации.

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

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

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
...