Разбор файла с разделителями табуляции и двойными кавычками в Perl - PullRequest
2 голосов
/ 03 января 2011

У меня есть набор данных, разделенный табуляцией со строками пользовательского агента в двойных кавычках. Мне нужно проанализировать каждый из этих столбцов и, основываясь на ответе моего другого сообщения , я использовал модуль Text :: CSV.

94410634  0   GET  "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB6.6; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; AskTB5.5)"   1

Код простой.

#!/usr/bin/perl

use strict;
use warnings;
use Text::CSV;

my $csv = Text::CSV->new(sep_char => "\t");

    while (<>) {
        if ($csv->parse($_)) {
            my @columns = $csv->fields();
            print "@columns\n";
        } else {
            my $err = $csv->error_input;
            print "Failed to parse line: $err";
        }
    }

Но я получаю ошибку Failed to parse line:, когда пытаюсь это сделать с этим набором данных. Что я делаю неправильно? Мне нужно извлечь 4-й столбец, содержащий строки агента пользователя для дальнейшей обработки.

1 Ответ

6 голосов
/ 03 января 2011
  1. Ваши аргументы конструктора должны быть в хеш-адресе, а не в хэше:

    my $ csv = Text :: CSV-> new ({sep_char => "\ t"});

  2. Вы уверены, что набор данных именно такой, как вы думаете?Может быть, где-то пропущена двойная кавычка или нет вкладок?

    Чтобы проверить содержимое файла, вы используете Unix / Linux или Windows?В Unix, пожалуйста, запустите это: cat -vet my_log_file_name | head -3 и проверьте, есть ли в выводе пробелы или последовательности «^ I», где вы ожидаете вкладки.cat -vet выводит все специальные символы в виде специальных печатаемых последовательностей (TAB => ^I, символ новой строки => $ и т. Д.)

Следующий тестотлично работает на моем ActivePerl:

#!/usr/bin/perl
use strict;
use warnings;
use Text::CSV;

my $s = qq[94410634\t0\tGET\t"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB6.6; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; AskTB5.5)"\t1\n];;
my $csv = Text::CSV->new({sep_char => "\t"});

if ($csv->parse($s)) {
    my @columns = $csv->fields();
    print "c=$columns[3]\n";
} else {
    my $err = $csv->error_input;
    print "Failed to parse line: $err";
}

Вывод :

C:\> perl d:\scripts\test4.pl
c=Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB6.6; ...
...