2012-03-05 4 views
0

У меня есть входной файл со следующим синтаксисом:Perl использование сплит функции

00000 INFO [IVS ] reset receiver 
00000 INFO [IVS ] reset transmitter 
00331 INFO [IVS ] sync detected  

Необходимые данные в виде

frame=0000 
info=INFO 
TYPE=[IVS ] 
message=reset receiver 

($frame,$info,$type,$message)=split(what would be the argument?); 

Примечание: пробел после СПВ перед скобкой, поэтому не могу использовать пространство как разделитель.

+0

Вашего входа фиксированной шириной, вкладка/пробела, или что-то еще? Чтобы правильно разбить данные, вам нужно знать, как генерируются данные. Итак: Узнайте. – TLP

ответ

2

Я согласен с @hobbs, но вы должны использовать расширенный формат для сложных регулярных выражений:

while(my $line = <DATA>){ 
    chomp $line; 

    my ($frame, $info, $type, $message) = 
    $line =~ m{ 
     \A  # start at the beginning of the string 
     (\d+)  # capture a string of digits  --> $frame 
     \s+  # skip the white space 
     (\S+)  # capture a string of non-spaces --> $info 
     \s+  # skip the white space 
     (  # start a capture     --> $type 
     \[  # capture an opening bracket 
     [^\]]* # capture everything that's not a closing bracket 
     \]  # capture the closing bracket 
    )   # end the capture 
     \s+  # skip the white space 
     (.*)  # capture the remainder of the line --> $message 
    }msx; 

    print "\$frame = $frame\n"; 
    print "\$info = $info\n"; 
    print "\$type = $type\n"; 
    print "\$message = $message\n"; 
    print "\n"; 
} 

__DATA__ 
00000 INFO [IVS ] reset receiver 
00000 INFO [IVS ] reset transmitter 
00331 INFO [IVS ] sync detected 
7

Неправильный вопрос. Вы не хотите использовать split. Эмпирическое правило: используйте регулярное выражение, когда вы знаете, как выглядят ваши данные; используйте split, когда вы знаете, как выглядят ваши разделители.

my ($frame, $info, $type, $message) = 
    $data =~ /(\d+) (\S+)\s+\[(\S+)\s*\] (.*)/; 

было бы неплохо начать.

+0

спасибо, а также не могли бы вы указать мне на какой-то сайт для хорошего начала изучения perl? – fammi

2

Вы хотите разделить пространство, если за пространством не следует ]. Это означает, что вы хотите использовать негативный прогноз в своем регулярном выражении. Не забывайте, что split() может принимать регулярное выражение в качестве первого аргумента. Он также может принимать количество полей, которые он возвращает, поэтому, если вы выполните:

my ($frame, $info, $type, $message) = split(/\s+(?!])/, $line, 4); 

... тогда вы получите то, что хотите.

Этот split() разбит на один или несколько пробельных символов, за которыми не следует ]. Он также возвращает четыре поля, поэтому вы не разделите свое поле $message (все после третьего раскола просто закончится в $message).

+0

спасибо, полезно, и я новичок в perl, любая рекомендация о том, где учиться на веб-сайте? – fammi

+0

Официальная документация по регулярному выражению в основном находится в [perlretut] (http://p3rl.org/retut) и [perlre] (http://p3rl.org/perlre). - Чтобы узнать Perl в целом, доверяйте ресурсу, указанному на http://learn.perl.org и http://perl-tutorial.org. Вы могли бы найти эту информацию самостоятельно, выполнив поиск переполнения стека, это далеко не редкий запрос. – daxim

+0

@fammi: Также см. [Современный Perl] (http://www.onyxneon.com/books/modern_perl/index.html). Он доступен для загрузки в различных форматах. –

3

Я люблю регулярные выражения, но ... TIMTOWTDI также.)

while (<DATA>) { 
    printf "frame=%s\ninfo=%s\nTYPE=%s\nmessage=%s\n", 
    unpack("A6 A6 A7 A*", $_); 
} 

__DATA__ 
00000 INFO [IVS ] reset receiver 
00000 INFO [IVS ] reset transmitter 
00331 INFO [IVS ] sync detected 

серьезно, то дело в том, что это могло бы быть лучше, чтобы разделить ваши данные-строку с одним простым unpack (да, распаковывать просто, это просто нужно немного практики ...)), чем с некоторыми перевернутыми регулярными выражениями - конечно, если все столбцы данных имеют фиксированную ширину. Но иногда это так.)