2012-04-16 3 views
2

После попытки N + 1 раз с регулярным выражением в Perl: Я следующую задачу: Мне нужно, чтобы получить это:Regular Expression Perl котировальный период

232310..1.3  3213 2.4 "$250 For My jacket" (2012) 

Я пытаюсь получить его с помощью:

if ($line=~m/^\s+(\d+|\.+)\s+(\d+)\s+(\d+|\.+)\s+(\^"&(\w*|\s*|\D*)"$)\s*\((\d+)\s*/){ 
     $ID=$1; 
     $Amount=$2; 
     $Size=$3; 
     $Item=$4; 
     $Year=$5; 

Это не работает

ответ

6

(\d+|\.+) означает, что либо один или несколько цифр или один или несколько периодов. Но то, что вы хотите, это ([\d.]+), что означает одну или несколько цифр или периодов.

Аналогичные проблемы выходят для захвата размера и предмета. Также вы неправильно используете стартовый якорь (^) и концевой якорь ($).

Вы можете попробовать:

^\s+([\d.]+)\s+(\d+)\s+([\d.]+)\s+"([^"]+)"\s*\((\d+)\s* 

See it

+0

Спасибо, что сработало отлично! ... Я тоже проверяю ссылку! Звучит неплохо. Кажется, что Ruby использует тот же синтаксис для регулярного выражения, что и perl! :) –

+0

Я не совсем понял («^»] +) », не могли бы вы объяснить? –

+0

« »», один или несколько символов, кроме « "", тогда """. Часть в кавычках фиксируется. – ikegami

1

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

(я бы отправил это как комментарий, но ограниченные возможности форматирования) решение

my ($id, $amount, $size, $item, $year) = $line =~ m{ 
    ^
    \s+ 
    ([\d.]+)  # field 1, e.g. 232310..1.3 
    \s+ 
    (\d+)   # field 2, e.g. 3213 
    \s+ 
    ([\d.]+)  # field 3, e.g. 2.4 
    \s+ 
    "([^"]+)"  # field 4, e.g. "$250 For My jacket" 
    \s* 
    \((\d+)\)  # field 5, e.g. (2012) 
    \s* 
}x or die "Line does not match!"; # always check that a regex actually succeeded! 
2

codaddict является штраф, если все ваши 4-записи строки в кавычки. Другой подход заключается в использовании анализатор CSV (который вы, вероятно, необходимо установить из CPAN первого), , например:

#!/usr/bin/env perl 

use strict; 
use warnings; 

use Text::CSV_XS; 

my $csvr = new Text::CSV_XS({ 
    sep_char => ' ', 
    eol => $/ 
}); 

my $csvw = new Text::CSV_XS({ 
    sep_char => ',', 
    eol => $/ 
}); 

$csvw->print(*STDOUT, [ qw(ID Amount Size Item Year) ]); 

while (my $row = $csvr->getline(*ARGV)) 
{ 
    $csvw->print(*STDOUT, [ grep { /./ } @$row ]); 
} 

}

При введении на вход

232310..1.3  3213 2.4 "$250 For My jacket" (2012) 

это будет производить:

232310..1.3,3213,2.4,"$250 For My jacket",(2012) 

Следующий шаг заключается в использовании DBD::CSV, что позволяет выполнять SQL-запросы в вашем входном файле.

+0

Это действительно приятно, я вижу вашу точку зрения, но мы не можем просто напечатать $ id, $ Amount, $ Size и т. Д. Или есть что-то, что мне не хватает в файлах CSV? –

+0

Хороший комментарий об использовании парсера CSV - Текст :: CSV, возможно, является более простой альтернативой в зависимости от среды - он будет использовать XS, если установлен, чистый-perl, если нет. – plusplus

+0

@MajicJohnson - '$ id' и т. Д. В этом коде не существует.Для удобства чтения вы можете извлечь их в цикле из массива '$ row' arrayref следующим образом:' my ($ ID, $ Amount, $ Size, $ Item, $ Year) = @ {$ row}; ' – plusplus