preg_split: разбиение строки по очень специфическому шаблону - PullRequest
0 голосов
/ 18 января 2019

Regex / PHP n00b здесь.Я пытаюсь использовать функцию PHP "preg_split" ...

У меня есть строки, которые следуют очень специфическому шаблону, в соответствии с которым я хочу разделить их.

Пример строки:

CADAVRES [FILM] (Канада: Квебек, Эрик Кануэль, 2009, длинный метраж) FICTION

Желаемый результат:

[0]CADAVRES
[1]FILM
[2]Canada : Québec
[3]Érik Canuel
[4]2009
[5]long métrage
[6]FICTION

Разделители (в порядке появления):

" ["
"] ("
", "
", "
", "
") "

Как правильно написать регулярное выражение?

Вот что я пробовал:

<?php
$pattern = "/\s\[/\]\s\(/,\s/,\s/,\s/\)\s/";
$string = "CADAVRES [FILM] (Canada : Québec, Érik Canuel, 2009, long métrage) FICTION";
$keywords = preg_split($pattern, $string);
print_r($keywords);

Это не работает, и я не понимаю, что я делаю неправильно.Опять же, я только начал пытаться разобраться с регулярными выражениями и PHP, так что да ... Есть так много escape-символов, я не могу видеть прямо ...

Большое спасибо!

Ответы [ 3 ]

0 голосов
/ 18 января 2019

Вот попытка с preg_match:

$pattern = "/^([^\[]+)\[([^\]]+)\]\s+\(([^,]+),\s+([^,]+),\s+([^,]+),\s+([^,]+)\)\s+(.+)$/i";
$string = "CADAVRES [FILM] (Canada : Québec, Érik Canuel, 2009, long métrage) FICTION";
preg_match($pattern, $string, $keywords);
array_shift($keywords);
print_r($keywords);

Выход:

Array
(
    [0] => CADAVRES 
    [1] => FILM
    [2] => Canada : Québec
    [3] => Érik Canuel
    [4] => 2009
    [5] => long métrage
    [6] => FICTION
)

Попробуйте!

Распределение регулярных выражений:

^   anchor to start of string
 (    begin capture group 1
  [^\[]+   one or more non-left bracket characters
        )   end capture group 1
         \[   literal left bracket
           (   begin capture group 2
            [^\]]+   one or more non-right bracket characters
                  )    end capture group 2
                   \]   literal bracket
                     \s+    one or more spaces
                        \(    literal open parenthesis
                          (     open capture group 3
                           [^,]+   one or more non-comma characters
                                )     end capture group 3
                                 ,\s+     literal comma followed by one or more spaces
                                     ([^,]+),\s+([^,]+),\s+([^,]+)   repeats of the above
                                                                  \)   literal closing parenthesis
                                                                    \s+   one or more spaces
                                                                       (  begin capture group 7
                                                                        .+  everything else
                                                                           )  end capture group 7
                                                                            $ EOL

Это предполагает, что ваша структура статична и не особенно хороша, но, с другой стороны, должна быть устойчивой к разделителям, попадающим в поля, где они не должны быть. Например, заголовок, имеющий : или , в нем, кажется правдоподобным и может нарушить решение типа «разбить на эти разделители где угодно». Например,

"Matrix:, Trilogy()   [FILM, reviewed: good]    (Canada() :   Québec  ,  \t Érik Canuel , ): 2009 ,   long ():():[][]métrage) FICTIO  , [(:N";

правильно обрабатывает как:

Array
(
    [0] => Matrix:, Trilogy()   
    [1] => FILM, reviewed: good
    [2] => Canada() :   Québec  
    [3] => Érik Canuel 
    [4] => ): 2009 
    [5] => long ():():[][]métrage
    [6] => FICTIO  , [(:N
)

Попробуйте!

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

0 голосов
/ 18 января 2019

Вы можете использовать это регулярное выражение, чтобы разделить на:

([^\w:]\s[^\w:]?|\s[^\w:])

Он ищет не- (слово или :) символ, за которым следует пробел, за которым следует необязательный не- (слово или :); или пробел, за которым следует не (слово или :) символ. Это будет соответствовать всем вашим желаемым шаблонам разделения. В PHP (обратите внимание, вам нужен модификатор u для работы с символами Юникода):

$input = "CADAVRES [FILM] (Canada : Québec, Érik Canuel, 2009, long métrage) FICTION";
$keywords = preg_split('/([^\w:]\s[^\w:]?|\s[^\w:])/u', $input);
print_r($keywords);

Выход:

Array
(
    [0] => CADAVRES 
    [1] => FILM
    [2] => Canada : Québec
    [3] => Érik Canuel
    [4] => 2009
    [5] => long métrage
    [6] => FICTION
)

Демонстрация на 3v4l.org

0 голосов
/ 18 января 2019

Мне удалось разработать решение, используя preg_match_all:

$input = "CADAVRES [FILM] (Canada : Québec, Érik Canuel, 2009, long métrage) FICTION";
preg_match_all("|[^-\\[\\](),/\\s]+(?:(?: :)? [^-\\[\\](),/]+)?|", $input, $matches);
print_r($matches[0]);

Array
(
    [0] => CADAVRES
    [1] => FILM
    [2] => Canada : Québec
    [3] => Érik Canuel
    [4] => 2009
    [5] => long métrage
    [6] => FICTION
)

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

...