2015-04-11 4 views
0

Я новичок в Perl, и мне было интересно, может ли кто-нибудь помочь мне.Совпадение нескольких строк строки в Perl

У меня есть вход, как это:

a,b, 
c,d,e,f,g,h, 
i,j,q // Letras 

Я пытаюсь получить письма, прежде чем // отдельно, а затем распечатать их между {} отделенной :.

Я пробовал с этим RE ([\w,;:\s\t]*)(\n|\/\/)/m, и я мог бы получить в $1 все буквы для каждой строки (как строки, включая разделители), но не то, что я хочу.

Мне нужно сопоставить этот шаблон более одного раза в одном файле, поэтому я использовал /g.

Edit:

Вот мой код блока:

while (<>) { 
    if (/([\w,;:\s\t]*)(\n|\/\/)/m) { 
    print "$1\n"; 
    } 
} 
+0

Не могли бы мы увидеть, что вы пробовали? – John

+0

while (<>) { \t if (/ ([\ w,;: \ s \ t] *) (\ n | \/\ /)/m) { \t \t print "$ 1 \ n"; \t} } С этим я мог распечатать контент до //. – Bruno

ответ

2

/m для использования ^ и $, чтобы соответствовать по линии в строке с несколькими линиями.

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

Вместо этого прочитайте куски, установив $/ на соответствующее значение. Если куски всегда заканчиваются точной строкой "// Letras\n\n", задача еще проще.

#!/usr/bin/env perl 

use strict; 
use warnings; 

local $/ = '//'; 

while (my $chunk = <DATA>) { 
    chomp $chunk; 
    my @fields = ($chunk =~ /([a-z])[, ]/g); 
    next unless @fields; 
    printf "{%s}\n", join(':', @fields); 
} 

__DATA__ 
a,b, 
c,d,e,f,g,h, 
i,j,q // Letras 

a,b, 
c,d,e,f,g,h, 
i,j,q // Metras 

Выход:

{a:b:c:d:e:f:g:h:i:j:q} 
{a:b:c:d:e:f:g:h:i:j:q}

Вы также можете использовать File::Stream:

#!/usr/bin/env perl 

use strict; 
use warnings; 

use File::Stream; 

my $stream = File::Stream->new(
    \*DATA, 
    separator => qr{ (?: \s+ // [^\n]+) \n\n }x 
); 

while (my $chunk = <$stream>) { 
    $chunk =~ s{ \s+ // .* \z }{}sx; 
    $chunk =~ s{ ,\n? }{:}gx; 
    print "{$chunk}\n"; 
} 

__DATA__ 
a,b, 
c,d,e,f,g,h, 
i,j,q // Letras 

a,b, 
c,d,e,f,g,h, 
i,j,q // Metras 
+0

Это * много * спекуляций! – Borodin

+0

Вот что мне нужно! Я не знал, как читать файл, пока не прочитал '//'. Как работает этот кусок кода: my $ chunk = ? Каким должен быть мой DATA, если у меня есть входной файл .txt? Наконец, как это работает: next if @fields; ? Еще раз спасибо! – Bruno

+0

Откройте файл, используя обычный 'open my $ fh, '<', $ filename' ... Затем используйте' $ fh' вместо 'DATA'. –

1

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

Прежде всего, вы должны удалить концевую символ перевода строки из каждой строки с помощью chomp

Тогда все, что вам нужно удалить любой трейлинг комментарий s|\s*//.*||. Это удаляет любые пробелы до //. Я использую символ канала | в качестве разделителя, чтобы избежать необходимости сбрасывать косые черты в шаблоне регулярных выражений.И данные обрабатываются по одной строке за раз, так там нет необходимости для глобального/g модификатора

Эта программа считывает данные из файла, указанного в командной строке, которую я настроил, чтобы содержать данные, которые вы показать в вопросе

use strict; 
use warnings; 

while (<DATA>) { 
    chomp; 
    s|\s*//.*||; 
    print "{$_}\n"; 
} 

выход

{a,b,} 
{c,d,e,f,g,h,} 
{i,j,q} 

Update

Благодаря Sinan Ünür's solution я замечаю, что вы попросили «печать [на буквы] между {} разделенных :»

Это модификация while цикла выше, который находит все подстроки в пределах текущей строки, которые не содержат запятые, и присоединяется к ним снова вместе, используя двоеточие :

while (<>) { 
    chomp; 
    s|\s*//.*||; 
    my $values = join ':', /[^,]+/g; 
    print "{$values}\n"; 
} 

выход

{a:b} 
{c:d:e:f:g:h} 
{i:j:q} 

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

0

Вы хотите объединить буквы на всех 3-х линий в выход или преобразовать каждую строку?

Другими словами, ваш желаемый результат

{a:b} 
{c:d:e:f:g:h} 
{i:j:q} 

или

{a:b:c:d:e:f:g:h:i:j:q} 

?

Если вы хотите первого, ответ Бородина будет работать. Если вы хотите последний, то вы должны загрузить содержимое в массив и распечатать его с помощью инструкции объединения. Чтобы сделать это, я изменил ответ Бородина:

while (<>) { # read each line 
    chomp;   # remove \n from line 
    s|\s*//.*||; # remove comment 
    push @values, ':', /[^,]+/g; # store letters in array 
} 
my $values = join ':', @values; # convert array to string 
print "{$values}\n";    # print the results 
0
my $str = "a,b, 
c,d,e,f,g,h, 
i,j,q // Letras"; 

$str = join "",map {s/,/:/g ;(split)[0]} split '\n', $str; 

print "{$str}"; 


Sample output 

{a:b:c:d:e:f:g:h:i:j:q} 

Я рассматриваю строку с мультилиниями, разделенных символом новой строки.

join "",map {s/,/:/g ;(split)[0]} split '\n', $str 

Оценка получена справа налево.

  1. Разделить с \n на $str производит 3 элементы, которые введены для map.

  2. (split)[0]: разделитель по умолчанию для split - пробел. поэтому каждый элемент разделяется на пробелы, а элемент 0th считается отбрасыванием других. Ex (split)[0] для i,j,q // Letras производит 3 элемента "i, j, q" "//" "Letras", где рассматривается только элемент 0, т. Е. "I, j, q".

  3. , заменяется :

  4. join используется, чтобы объединить все полученные элементы из map.

Смежные вопросы