Не выделяйте текст в двойных квадратных скобках - PullRequest
2 голосов
/ 02 апреля 2019

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

Случай:

  • Существует словарь фраз.
  • Фразы с большим количеством словявляются «более сильными» / получили приоритет над фразами с более короткими словами.
  • Некоторые фразы являются частями других более длинных фраз.

Пример словаря (сортируется как массив в реальном коде):

Wooden House
House
Wooden

Пример текста, который нужно проанализировать:

Lorem ipsum Wooden House dolor sit amet

Синтаксический анализ выполняется с помощью preg_replace для текста, который нужно проанализировать, выполнив итерацию по словарю и добавив [[randomstaff-_-current dictionary phrase]], например, так:

Lorem ipsum Wooden House dolor sit amet -> Lorem ipsum [[randomstuff-_-Wooden House]] dolor sit amet.

в настоящее время после второй итерации оно становится: Lorem ipsum [[randomstuff-_-Wooden House]] dolor sit amet -> Lorem ipsum [[randomstuff-_-Wooden[[randomstuff-_-House]]]]

и я бы хотел оставить егобез изменений, если оно уже находится между [[ и ]].

Так что в основном, если совпадение равно где-нибудь между [[ и ]] - игнорируйте его.

$dictPhrases = ["Wooden House", "House", "Wooden"];
$TEXT = "Lorem ipsum Wooden House dolor sit amet";

for ($dictPhrases as $phrase){
 $phraseOccurences = 0; //irrelevant in this example
 $TEXT = preg_replace("/(?i)(?<= |^|\n)(" . $phrase. "[&()'-]{0,1})(?= |$|\.|\,)/", "[[$randomstuff-_-" . $phrase . "]]", $TEXT, -1, $phraseOccurences);

}

Вопрос в том, как поменять:

/(?i)(?<= |^|\n)(" . $phrase. "[&()'-]{0,1})(?= |$|\.|\,)/

на что-то вроде:

/(?i)(?<!\[\[.*)(?<= |^|\n)(" . $phrase. "[&()'-]{0,1})(?= |$|\.|\,)(?!.*\]\])/

, чтобы увидеть совпадениеФраза ed не находится между [[ и ]] и отбросьте ее, если она есть.

Ответы [ 2 ]

0 голосов
/ 06 апреля 2019

Возможно, есть два решения для этого.

1) Получить начальную позицию соответствия, найти все "[[" и "]]" в подстроке (0, первый символ соответствия) и изменить их на 22) Получить начальную позицию соответствия, получить последнюю позицию «[[» и последнюю позицию «]]» в подстроке (0, первый символ соответствия) и проверить, какая из них ближе.

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

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

0 голосов
/ 02 апреля 2019

Просто преобразуйте

["Wooden House", "House", "Wooden"]

в одно регулярное выражение:

"(?:Wooden House|House|Wooden)"

и затем поместите его в основное регулярное выражение.

Попробуйте что-то вроде этого:

$dictPhrases = ["Wooden House", "House", "Wooden"];
$TEXT = "Lorem ipsum Wooden House dolor sit amet";

$pattern = "/(?i)(?<= |^|\n)((?:" . join('|', $dictPhrases) . ")[&()'-]{0,1})(?= |$|\.|\,)/";

$phraseOccurences = preg_match_all($pattern, $TEXT);
$TEXT = preg_replace($pattern, "[[$randomstuff-_-$1]]", $TEXT);

Здесь Демонстрация регулярных выражений.

Здесь Демонстрация PHP.

...