обработка текста на Perl (в частности, при загрузке файлов) - PullRequest
0 голосов
/ 13 февраля 2019

Загрузка файлов и сортировка столбцов в оболочке обычно проста с комбинацией grep, cut, sed, awk и т. Д.

Однако, когда мне приходится это делатьв Perl я часто заканчиваю тем, что выполняю долгие и мучительные вещи, используя множество разделений, одно за другим, регулярные выражения, и в результате получается грязный код, который выглядит примерно так:

open $FH, "<", $file;
@file = <$FH>;
close $FH;
foreach $line (@file) {
    ( $foo, $bar, $some, $thing) = ( split(/,/, $line) )[3,8,9,15] 
    ( $new_some ) = (split(/-/, $some))[2];
    ($new_foo = $foo) =~ s/xx//;
    $uc_bar = uc($bar);
    # and so on.....
}

элегантный способ делать такие вещи (разделение полей, замена шаблонов и т. д.)?Или более «более быстрый» способ (не обязательно элегантный)?

Также есть способ загрузить только необходимую часть файла во время загрузки (без необходимости загружать все в память, но фильтровать передзагрузка)?

1 Ответ

0 голосов
/ 13 февраля 2019

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

"есть способ загрузить только необходимую частьфайла во время загрузки " - в показанном вами коде я не вижу необходимости загружать весь файл в память.Типичным шаблоном для обработки файлов построчно и эквивалентом того, что делают -n и -p переключатели Perl , является этот шаблон:

open my $fh, '<', $file or die "$file: $!";
while (<$fh>) {          # reads line into $_
    my @fields = split;  # splits $_ on whitespace, like awk
    my ($foo, $bar, $some, $thing) = @fields[3,8,9,15];
    ...
}
close $fh;

Я считаю, чтодовольно элегантно, но, исходя из того, что вы пишете, я полагаю, вы сравниваете это со списком команд, переданных по трубопроводу, которые вмещают, возможно, 100 символов.Perl тоже может это сделать: как уже упоминалось в комментариях, взгляните на переключатели -n, -p, -a, -F и -i.Если вы покажете несколько конкретных примеров того, что вы хотите сделать, вы, вероятно, получите ответы, показывающие, как сделать это короче с помощью Perl.

Но если вы собираетесь делать больше, то обычно лучшечтобы развернуть это в сценарий, подобный приведенному выше.ИМХО, помещая вещи в сценарий, вы получаете больше возможностей: он не эфемерный, как история командной строки, он более легко расширяется, и его проще использовать для модулей, вы можете добавлять параметры командной строки, обрабатывать несколько файлов и так далее.Например, со следующим фрагментом вы получаете всю мощь Text::CSV - поддержку цитирования, экранирования, многострочных строк и т. Д.

use Text::CSV;
my $csv = Text::CSV->new({binary=>1, auto_diag=>2, eol=>$/});
open my $fh, '<', $file or die "$file: $!";
while ( my $row = $csv->getline($fh) ) {
    ...
    $csv->print(select, $row);
}
$csv->eof or $csv->error_diag;
close $fh;

Возможно, вы также захотитепроверьте функцию csv этого модуля, которая предоставляет множество функций в короткой функции.Если вы все еще думаете, что это все «болезненно» и «грязно» , и вы предпочитаете делать вещи с меньшим количеством кода, то есть несколько комбинаций, которые вы можете использовать, например, дляотбросить весь файл в память, my $data = do { local (*ARGV, $/) = $file; <> };, или сделать то же самое, что и ключ командной строки -i:

local ($^I, @ARGV) = ('.bak', $file);
while (<>) {
    # s///; or @F=split; or whatever
    print;  # prints $_ back out
}

В Perl мне нравится то, что он позволяет вам выражать себя в большом количестверазных способов - хотите ли вы собрать по-настоящему короткий сценарий для решения одноразовой задачи или написать большой проект OO, TIMTOWTDI ?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...