Perl Text Parsing - фиксированная разделенная структура меняется - PullRequest
1 голос
/ 20 января 2011

Эксперты Perl - Моя попытка решить мою проблему превращается в большой код, который в PERL выглядит так, будто я неправильно подхожу к этому. Вот моя проблема:

У меня есть блок текста (пример ниже), который может иметь переменное количество пробелов между данными столбца. Я использовал простое разбиение, но теперь проблема заключается в том, что столбец «код» теперь содержит пробелы в данных (я учел это только в последнем столбце). То, что кажется постоянным (хотя у меня нет доступа или контроля над исходной структурой), это то, что между столбцами есть минимум 3 пробела (может быть больше, но никогда не меньше).

Итак, я хотел бы сказать, что мой маркер разделителя столбцов равен «3 пробела», а затем обрезать данные внутри каждого из них, чтобы получить мои фактические данные столбцов.

COL0   COL1   COL2   COL3         COL4   COL5
   -      4    0.2      1       416489   463455 554
          1    0.9      1           E1   
   0      3    1.4     14   E97-TEST 1   
   -      1   97.5    396         PASS   Good

Я просто пытаюсь получить значения в 6 переменных.

ПРИМЕЧАНИЕ. COL0 может не иметь значения. COL4 может содержать пространство в данных. COL5 может не содержать значения или данных с пробелом. Все фиксированное форматирование выполняется с пробелами (без вкладок и других специальных символов). Чтобы уточнить - столбцы НЕ одинакового размера. Один файл может иметь COL4 как 13 символов, другой - COL4 с шириной 21 символа. Или не строгий, как заявил другой член SO.

Ответы [ 4 ]

3 голосов
/ 21 января 2011

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

my @file = <file>;
chomp @file;

my $t = "";
$t |= $_ foreach(@file);

$ t будет содержать пробельные символы в столбцах только там, где в них всегда были пробельные символыколонка;другие столбцы будут содержать двоичный мусор.Теперь разделите его на совпадение с нулевой шириной, которое соответствует непробелу:

my @cols = split /(?=[^ ]+)/, $t;

Мы действительно хотим, чтобы ширина столбцов генерировала формат unpack ():

@cols = map length, @cols;
my $format = join '', map "A$_", @cols;

Теперь обработайте файл!:

foreach my $line (@file) {
  my($field, $field2, ...) = unpack $format, $line;
  your code here...
}

(Этот код был проверен лишь незначительно.)

2 голосов
/ 20 января 2011

Если вы имеете дело со строгими столбчатыми данными, как это, unpack, вероятно, то, что вы хотите:

#!perl

use strict;
use warnings;
use 5.010;

use Data::Dumper;

my $data = <<EOD;
COL0   COL1   COL2   COL3         COL4   COL5
   -      4    0.2      1       416489   463455 554
          1    0.9      1           E1   
   0      3    1.4     14   E97-TEST 1   
   -      1   97.5    396         PASS   Good
EOD

my @lines = split '\n', $data;
for my $line ( @lines ) {
    my @values = unpack("a5 A7 A7 A7 A13 A*", $line);
    print Dumper \@values;
}

Похоже, что ваши значения выгружаются в массив @values по вашему желанию, но они будут иметь начальные пробелы, которые вам придется обрезать.

1 голос
/ 21 января 2011

Я бы использовал два прохода: во-первых, найдите те столбцы символов, которые имеют пробел в каждой строке; затем разделить или распаковать с этими индексами. Обрезка пробелов выполняется позже.

Ваш пример:

COL0   COL1   COL2   COL3         COL4   COL5
   -      4    0.2      1       416489   463455 554
          1    0.9      1           E1   
   0      3    1.4     14   E97-TEST 1   
   -      1   97.5    396         PASS   Good

000011100001110000111000011100000000001110000000000

1 в последней строке показывают, какие столбцы являются пробелами.

0 голосов
/ 20 января 2011

Я знаю, что CanSpice уже ответил (возможно, намного лучшее решение), но вы можете установить разделитель ввода, используя "$ /". Это должно быть сделано в локальной области (вероятно, в подпрограмме), поскольку это глобальная переменная, иначе вы можете увидеть побочные эффекты. Пример:

local $/ = "   ";
$input = <DATAIN>; # assuming DATAIN is the file-handler

Вы можете обрезать пробелы, используя милое регулярное выражение. См. Википедия для примера.

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