2014-11-21 3 views
0

Мне нужно сопоставить несколько шаблонов в одной строке. Например, в этом файле:Необходимо сопоставить несколько шаблонов в одной строке - Perl

Hello, Chester [McAllister;Scientist] lives in Boston [Massachusetts;USA;Fenway Park] # McAllister works in USA 
I'm now working in New-York [NYC;USA] # I work in USA 
... 

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

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

[McAllister;Scientist] & [Massachusetts;USA;Fenway Park] TO "McAllister works in USA" 
+1

Вы имеете в виду это '\ [[^; \ n] * (?:; [^; \ N] *) + \]' http://regex101.com/r/uT5cC0/2 ' –

+0

Что вы пытаясь сделать это, получить их в массив? – sln

+0

@AvinashRaj Я пробовал это 'if ($ sentence = ~/(\ [[;;] * (?:; [^;] *) + \])/G) {\t print $ 1."\ П"; } ', но для первой строки результат:« [McAllister, Scientist] живет в Бостоне [Массачусетс, США, Fenway Park] ' –

ответ

-1

tidiest способ возможно использовать регулярное выражение, чтобы найти все встроенные последовательности, ограниченные квадратные скобки, а затем использовать map с split, чтобы отделить эти последовательности в термины.

Эта программа демонстрирует.

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

use strict; 
use warnings; 

my $s = <<END_TEXT; 
Hello, Chester [McAllister;Scientist] lives in Boston [Massachusetts;USA;Fenway Park] # McAllister works in USA 
I'm now working in New-York [NYC;USA] # I work in USA 
END_TEXT 

my @data = map [ split /;/ ], $s =~/\[ ([^\[\]]+) \] /xg; 

use Data::Dump; 
dd \@data; 

выходных

[ 
    ["McAllister", "Scientist"], 
    ["Massachusetts", "USA", "Fenway Park"], 
    ["NYC", "USA"], 
] 
+0

Действительно powerpul –

-2

Модифицированный - Учитывая Ваш обновленный пост, это способ, которым Вы могли бы это сделать.
Это своего рода раскол в основном регулярном выражении через конструкцию кода блока (?{}).
Немного сложно это сделать, но это позволяет избежать выполнения дополнительного регулярного выражения.

Основное регулярное выражение создает массив @vals и получает целевую строку # target..
в каждом матче. Его строго ориентированная линия. В каждом матче регулярное выражение построено
с @vals и используется для соответствия объекту цели.

Удачи вам!

Perl

use strict; 
use warnings; 

$/ = undef; 
my $data = <DATA>; 

my @vals; 

while ($data =~/
    ^      # BOL 
    (?{ @vals =() })  # Code block - Initialize @vals 
    (?:      # Text & vals cluster 
      [^\n\[]*     # Text - not newline nor '[' 
      \[      # '[' opening vals bracket 
      (?:      # Vals cluster 
       ([^\n;\]]*)   # (1), Optional value 
       ;?      # Optional ';' 
       (?{ 
        # Code block - Push capture onto @vals 
        push (@vals, $^N) 
        if length $^N; 
       }) 
     )*      # End Vals cluster, do 0 to many times 
      \]      # ']' closing val bracket 
    )*      # End Text & vals cluster, do 0 to many times 
    [^\n#]*     # Text - not newline nor '#' 
    \#      # '#' Target string delimiter 
    (.*)     # (2), Optional Target string 
    $      # EOL 
    /xmg) 
{ 
    my $target = $2; 
    print "----------\n$target\n"; 
    if (@vals) { 
     my $rx = '(' . join('|', map { quotemeta } @vals) . ')'; 
     my $matched = 0; 
     while ($target =~ /$rx/g) { 
      print "$1,"; $matched = 1; 
     } 
     print "\n" if $matched; 
    } 
} 

__DATA__ 

Hello, Chester [McAllister;Scientist] lives in Boston [Massachusetts;USA;Fenway Park] # McAllister works in USA 
I'm now working in New-York [NYC;USA] # I work in USA 
Nothing [here;;; 
Nothing [there;;story;] [;] # End of here story 
# More junk here 

Выход

McAllister works in USA 
McAllister,USA, 
---------- 
I work in USA 
USA, 
---------- 
End of here story 
story, 
---------- 
More junk here 
+0

* Любая строка на всех *, которая не содержит закрывающий скобок ']' будет соответствовать '/ [^; \]] * (?:; [^; \]] *) */X'. Нет необходимости упоминать точки с запятой ';' вообще, и просто '/ [^ \]] * /' будет иметь одинаковый эффект. – Borodin

-1

Попробуйте

Это также дает то, что вы ожидаете.

use strict; 
use warnings; 
open('new',"file.txt"); 
my @z =map{m/\[[\w;\s]+\]/g} <new>; 
print "$_ ,",foreach(@z); 

Вы на самом деле нужно соответствовать слова, разделенные ; в [].

+0

кто проголосует за добавление комментария – mkHun

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