С 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 $_;
}
Чтобы пропустить строки, используйте циклические элементы управления. next
в этом примере пропускает строки комментариев, а last
останавливает всю обработку, как только встречает __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
, дайте -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