Обработка файлов в Perl

#perl #csv #text

#perl #csv #текст

Вопрос:

У меня есть простой csv-файл, в котором есть данные, которые я хочу извлечь из записи в новый файл.

Я хочу написать скрипт, который читает файл, считывает каждую строку, затем разбивает и структурирует столбцы в другом порядке, и если строка в .csv содержит ‘xxx’ — не выводите строку в выходной файл.

Мне уже удалось прочитать файл и создать дополнительный файл, однако я новичок в Perl и все еще пытаюсь разобраться с командами, ниже приведен тестовый скрипт, который я написал, чтобы освоиться с Perl, и мне было интересно, могу ли я изменить это на то, что мне нужно?-

 open (FILE, "c1.csv") || die "couldn't open the file!";
open (F1, ">c2.csv") || die "couldn't open the file!";

#print "startn";

sub trim($);

sub trim($)
{
    my $string = shift;
    $string =~ s/^s //;
    $string =~ s/s $//;
    return $string;
}

$a = 0;
$b = 0;
while ($line=<FILE>)
{
    chop($line);

    if ($line =~ /xxx/)
    {
        $addr = $line;
        $post = substr($line, length($line)-18,8);
    }
    $a = $a   1;
}

print $b;
print " endn";
  

Любая помощь приветствуется.

Комментарии:

1. Я подумал, что дам вам пару указаний по стилю, надеюсь, вы не возражаете. 0. Поместите use strict; и use warnings; в начало всех ваших скриптов. Вам придется объявлять переменные с помощью my , но это сэкономит вам время отладки в долгосрочной перспективе — пример my $foo = bar(); 1. В perl нет необходимости предварительно раскрывать ваши подпрограммы — за более чем десятилетие интенсивного использования Perl мне никогда не требовалась эта функция. 2. В общем, не используйте прототипы на своих дочерних устройствах, они работают не так, как на других языках. Это всего лишь подсказки компилятора, и их можно легко обойти.

2. Больше указателей стиля. 3. Переменные $a и $b являются специальными переменными, используемыми sort . Лучше не использовать их где-либо еще. Это может быть безопасно, если вы убедитесь, что они имеют лексическую область видимости, но, в общем, я их избегаю. 4. Дескрипторы файлов, подобные FILE , являются глобальными переменными, и их лучше всего заменить лексическими дескрипторами. 5. Open имеет форму с 3 аргументами и форму с 2 аргументами. Версия с двумя аргументами сохранена для обратной совместимости, но у нее есть некоторые проблемы. Вместо этого используйте форму аргумента 3. Пример современного 3-аргументного открытого: open my $fh, '>', $path_to_some_file or die "Didn't work: $!n"; .

3. Большинство этих проблем с вашим кодом связаны с устаревшими или запутанными документами. К счастью, существуют источники более современного использования Perl. » Эффективное программирование на Perl» Брайана Д. Фоя и » Современный Perl » Хроматика — пара превосходных книг. Современный Perl даже доступен для бесплатного скачивания: onyxneon.com/books/modern_perl/index.html

Ответ №1:

Для работы с CSV-файлами лучше использовать один из доступных модулей в CPAN. Мне нравится текст::CSV:

 use Text::CSV;

my $csv = Text::CSV->new ({ binary => 1, empty_is_undef => 1 }) or die "Cannot use CSV: ".Text::CSV->error_diag ();

open my $fh, "<", 'c1.csv' or die "ERROR: $!";
$csv->column_names('field1', 'field2');
while ( my $l = $csv->getline_hr($fh)) {
    next if ($l->{'field1'} =~ /xxx/);
    printf "Field1: %s Field2: %sn", $l->{'field1'}, $l->{'field2'}
}
close $fh;
  

Комментарии:

1. Спасибо за ввод, но он выдает ошибку «Не удается найти текст / CSV.pm в @INC <@INC содержит: C:/Perl/site/lib C:/Perl/Lib .>

2. Я полностью согласен с PacoRG; Text::CSV — правильный путь здесь.

3. Ламбо: сначала вам нужно установить Text::CSV модуль. Попробуйте установить его из PPM, следуя приведенным здесь инструкциям: docs.activestate.com/activeperl/5.10/faq/ActivePerl-faq2.html

4. ах, я вижу, что мне этого не хватало! Спасибо за это, я его установлю.

5. Если Text::CSV не установлен в вашей системе и у вас нет времени на его установку, альтернативой может быть использование модуля Text ::ParseWords, который поставляется как часть стандартной установки Perl и, следовательно, уже будет установлен.

Ответ №2:

Если вам нужно сделать это только один раз, чтобы программа не понадобилась позже, вы можете сделать это с помощью oneliner:

 perl -F, -lane 'next if /xxx/; @n=map { s/(^s*|s*$)//g;$_ } @F; print join(",", (map{$n[$_]} qw(2 0 1)));'
  

Разбивка:

 perl -F, -lane
     ^^^   ^ <- split lines at ',' and store fields into array @F

next if /xxx/;    #skip lines what contain xxx

@n=map { s/(^s*|s*$)//g;$_ } @F;
    #trim spaces from the beginning and end of each field
    #and store the result into new array @n

print join(",", (map{$n[$_]} qw(2 0 1)));
    #recombine array @n into new order - here 2 0 1
    #join them with comma
    #print
  

Конечно, для повторного использования или в более крупном проекте вам следует использовать какой-нибудь модуль CPAN. И в приведенном выше oneliner тоже много оговорок.