Как я могу извлечь кучу чисел из строки? - PullRequest
1 голос
/ 07 мая 2009

Это образец тестового файла:

  Barcode:*99899801000689811* 
  JSC4000I accountNumber:10006898Sequence Number:998 Envelopes: 1 
  LCD5010V Using jsl 'CUSOFF' for output page '6'
  Barcode:*99999901000673703* 
  LCD5010V Using jsl 'CUSOFF' for output page '4'
  LCD5005V Using job 'A' for current page '4'

Итак, в этом файле, как найти слово Barcode и извлечь его первые пять цифр, одновременно передав его в массив.

Заранее спасибо.

Ответы [ 4 ]

6 голосов
/ 07 мая 2009

Попробуйте регулярное выражение, что-то вроде этого должно работать:

Barcode:\*(\d{5})

1 голос
/ 07 мая 2009

Регулярные выражения - один из способов. Однако, просто для того, чтобы бросить в вас что-то совершенно другое, вот как справиться с этим с index и substr:

my @array;
foreach my $line ( <$file> ) {
    if ( index( $line, 'Barcode:' ) == 0 ) {
        push @array, substr $line, 9, 5;
    }
}
0 голосов
/ 10 мая 2009

Сравнение с шаблоном в контексте массива вернет значения, отмеченные ('(' и ')') в виде списка. Объедините это с модификатором зацикливания 'g' для повторного соответствия, и вы можете делать все это в одной строке, и мне нравится думать, что он очень удобочитаемый.

my $string =<<'HERE';
Barcode:*99899801000689811* 
JSC4000I accountNumber:10006898Sequence Number:998 Envelopes: 1 
LCD5010V Using jsl 'CUSOFF' for output page '6'
Barcode:*99999901000673703* 
LCD5010V Using jsl 'CUSOFF' for output page '4'
LCD5005V Using job 'A' for current page '4'
HERE

my @array = $string =~ m!Barcode:\*([0-9]{5})[0-9]+\*!g;

# or

foreach my $barcode ($string =~ m!Barcode:\*([0-9]{5})[0-9]+\*!g)
{
    # do stuff with $barcode
}
0 голосов
/ 10 мая 2009

Мое решение похоже на решение Манни, но я рекомендую использовать while для построчного чтения файла. Вы можете использовать substr (), как он, но регулярное выражение с якорями и без квантификаторов будет довольно быстрым:

my @barcodes;
while( <$fh> )
    {
    next unless m/^Barcode:\*([0-9]{5})/;

    push @barcodes, $1;
    }

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

my @barcodes = map { m/^Barcode:\*([0-9]{5})/ } <$fh>;

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

Якорь \ G получает совпадение с регулярным выражением, в котором вы остановились с последним совпадением в той же строке, в данном случае сразу после двоеточия:

my @barcodes;
while( <$fh> )
    {
    next unless m/^Barcode:/;

    unless( m/\G\*([0-9]{5])/ )
        {
        warn "Barcode is missing number at line $.\n";
        next;
        }

    push @barcodes, $1;
    }
...