Как я могу написать только определенные строки файла в Perl?

Я ищу способ прочитать входной файл и распечатать только выделенные строки в выходной файл в Perl. Строки, которые я хочу напечатать в выходной файл, начинаются с xxxx.xxxx.xxxx, где x - буквенно-цифровой символ (периоды-это периоды, а не подстановочные знаки). Не все строки имеют одинаковое окончание, если это имеет значение. Я думаю что-то вроде следующего (состояние if утверждение, что на самом деле, насколько я могу рассказывать.)

open(IN, "<$csvfile");
my @LINES = <IN>;
close(IN);
open(OUT, ">$csvnewfile");
print OUT @LINES if ([line starts with xxxx.xxxx.xxxx]);
close(OUT);

спасибо заранее!

7 ответов


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

use strict;
use warnings;

open my $fhi, '<', $csvfile    or die "Can not open file $csvfile: $!";
open my $fho, '>', $csvnewfile or die "Can not open file $csvnewfile: $!";
while (<$fhi>) {
    print $fho $_ if m/^ \w{4} \. \w{4} \. \w{4} /x;
}
close $fho;
close $fhi;

имейте в виду, что \w класс символов также включает символы подчеркивания. Чтобы избежать подчеркивания:

print $fho $_ if m/^ [a-z\d]{4} \. [a-z\d]{4} \. [a-z\d]{4} /xi;

модные советы:

  • использовать лексические filehandles
  • проверяем результат open
  • также хорошая идея, чтобы проверить результат close на ручке, открытой для записи

см. ниже:

#! /usr/bin/perl

use warnings;
use strict;

die "Usage:  old new\n" unless @ARGV == 2;

my($csvfile,$csvnewfile) = @ARGV;

open my $in,  "<", $csvfile    or die ": open $csvfile: $!";
open my $out, ">", $csvnewfile or die ": open $csvnewfile: $!";

while (<$in>) {
  print $out $_ if /^\w{4}\.\w{4}\.\w{4}/;
}

close $out or warn ": close $csvnewfile: $!";

используя grep

 grep "^\w\{4\}\.\w\{4\}\.\w\{4\}\b" file

if ($_ =~ m/^\w{4}\.\w{4}\.\w{4}/i)

Я думаю. Мой perl немного заржавел.


С 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 $_;
    }

закрыть $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 $_;
    }

закрыть $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 $_;
    }

закрыть $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 $_;
    }

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

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 one-liners для изменения файла на месте. Следующее изменяет все "Фред" на "Барни" в inFile.txt, перезапись файла с новым содержимым. С помощью переключателя-p Perl обертывает цикл while вокруг кода, который вы указываете с помощью-e, и-i включает редактирование на месте. Текущая строка находится в $. С -p Perl автоматически печатает значение $ в конце цикла. Дополнительные сведения см. В разделе perlrun.

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

сделать резервное копирование файлов.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

Если вы не против оставить его в качестве командной строки 1 вкладыш:

perl -ne "print if /^.{4}[.].{4}[.].{4}/" csvfile.csv > csvnewfile.csv

perl -ne 'print if /^\w{4}\.\w{4}\.\w{4}\b/' file > newfile.csv