Ответ 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