Возврат нескольких совпадений, но только до первого появления шаблона с использованием PHP и RegEX - PullRequest
3 голосов
/ 16 июня 2019

У меня есть набор данных, который выглядит как

I(0,123...789){
A(0,567...999){.......n=Marc.....}
B(2,655...265){..................}
C(3,993...333){..................}
M(8,635...254){.................;}
}
O(0,345...789){
A(0,567...999){.......n=Marc.....}
B(2,876...775){..................}
C(3,993...549){..................}
M(8,354...987){.................;}
}
I(0,987...764){
A(0,567...999){.......n=Marc.....}
B(2,543...265){..................}
C(7,998...933){..................}
M(8,645...284){.................;}
}
B(0,123...789){
.......
}
I(0,987...764){
A(0,567...999){.......n=John.....}
B(2,543...265){..................}
C(7,998...933){..................}
M(8,645...284){.................;}
}

Я пытаюсь вернуть все I "разделы", начиная с "I" до закрывающего тега, который следует после;}, но только еслиРаздел «I» содержит n = Marc.

До сих пор я пришел с

^([I]\(.*\){.*n=Marc.*^[M]\(.*;}.)}

https://regex101.com/r/VSuZh5/1

Однако в некоторых случаях, когда данные имеют шаблон, такой как

I(0,123...789){
A(0,567...999){.......n=Marc.....}
B(2,655...265){..................}
C(3,993...333){..................}
M(8,635...254){.................;}
}
O(0,345...789){
A(0,567...999){.......n=Marc.....}
B(2,876...775){..................}
C(3,993...549){..................}
M(8,354...987){.................;}
}

Регулярное выражение возвращает разделы I и O.Есть ли способ убедиться, что он всегда возвращает раздел I?

  • извиняюсь за набор данных, он огромен и содержит много конфиденциальных данных, которые я не могу опубликовать. *

Ответы [ 3 ]

2 голосов
/ 16 июня 2019

Одним из вариантов может быть совпадение I, затем сопоставление всех строк, которые не начинаются с }, и сопоставление хотя бы 1 строки, содержащей n=Marc

^I\([^()]*\){(?:\R(?!}|.*n=Marc).*)*\R.*\bn=Marc\b.*(?:\R(?!}).*)*\R}$

Пояснение

  • ^ Начало строки
  • I\([^()]*\){ Совпадение I, за которым следует (...){
  • (?: Группа без захвата
    • \R(?!}|.*n=Marc) Соответствует юникодной последовательности новой строки, утверждает, что справа не } или что строка содержит n = Marc
    • .* Соответствует любому символу 0+ раз
  • )* закрыть группу без захвата и повторить 0+ раз
  • \R Соответствует юникодной последовательности новой строки
  • .*\bn=Marc\b.* Соответствует любому символу 0+ раз и соответствует n=Marc между границами слова
  • (?: группа без захвата
    • \R(?!}).* Соответствует последовательности новой строки, утверждая, что справа не является }
  • )* Закрыть группу без захвата и повторить 0+ раз
  • \R Соответствие последовательности новой строки
  • } Закрытие матча }
  • $ Конец строки

Regex demo

2 голосов
/ 16 июня 2019

Если бы я знал, что входные данные всегда были отформатированы как образец, они скорее разбились бы на куски при закрытии } в начале строки, за которым следует новая строка, если за ней следует верхняя: ^}\R(?=[A-Z]).

Затем найдите элементы, начинающиеся с I и содержащие n=Marc, используя preg_grep.

$res = preg_grep('/^I.*n=Marc/s', preg_split('/^}\R(?=[A-Z])/m', $str));

См. Демонстрацию PHP на 3v4l.org

В вашем шаблоне .* может пропускать нежелательные элементы, что приводит к неожиданным совпадениям.

0 голосов
/ 16 июня 2019

Я предполагаю, что мы хотим, чтобы выражение возвращало секцию O с n=Marc, что-то похожее на:

(?=O\()([\s\S]*?n=Marc[\s\S]*?;}\s*})

Или, может быть:

(?=O\()([\s\S]*?n=Marc[\s\S]*?;})\s*}

Демо 1

Для I секций мы просто изменили бы O на I:

(?=I\()([\s\S]*?n=Marc[\s\S]*?;})\s*}

Демо 2

Тест

$re = '/(?=I\()([\s\S]*?n=Marc[\s\S]*?;})\s*}/m';
$str = 'I(0,123...789){
A(0,567...999){.......n=Marc.....}
B(2,655...265){..................}
C(3,993...333){..................}
M(8,635...254){.................;}
}
O(0,345...789){
A(0,567...999){.......n=Marc.....}
B(2,876...775){..................}
C(3,993...549){..................}
M(8,354...987){.................;}
}
I(0,987...764){
A(0,567...999){.......n=Marc.....}
B(2,543...265){..................}
C(7,998...933){..................}
M(8,645...284){.................;}
}
B(0,123...789){
.......
}
I(0,987...764){
A(0,567...999){.......n=John.....}
B(2,543...265){..................}
C(7,998...933){..................}
M(8,645...284){.................;}
}';

preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);

foreach ($matches as $key => $I) {
    echo $I[0] . "\n";
}

Выход

I(0,123...789){
A(0,567...999){.......n=Marc.....}
B(2,655...265){..................}
C(3,993...333){..................}
M(8,635...254){.................;}
}
I(0,987...764){
A(0,567...999){.......n=Marc.....}
B(2,543...265){..................}
C(7,998...933){..................}
M(8,645...284){.................;}
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...