Не выделять текст нигде между двойными квадратными скобками

#php #regex #pcre

#php #регулярное выражение #pcre

Вопрос:

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

Дело в:

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

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

 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. "[amp;()'-]{0,1})(?= |$|.|,)/", "[[$randomstuff-_-" . $phrase . "]]", $TEXT, -1, $phraseOccurences);

}
  

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

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

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

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

чтобы увидеть, не находится ли совпадающая фраза между [[ и ]] , и отбросить ее, если это так.

Комментарии:

1. Возможно, вы думаете об этом неправильно… Попробуйте разбить 1-ю итерацию на разные части. Затем на второй итерации вы можете манипулировать строкой из второй итерации с частями первой итерации. Так, например, ваша фраза из итерации может использоваться для выполнения string_replace(PHRASE_ONE, «, $secondIteration); Затем обработайте регулярное выражение в тех частях строки, которые остались для второй итерации. Как только это будет обработано, разбейте это и обработайте третье так, как вы сделали для второго. Повторяйте, пока не будет готово. Сопоставьте все это вместе в конце.

2. Ваш код не выполняет то, что вы описываете, поскольку замена выполняется только в том случае, если необязательно amp;()'- и обязательно ` $ .,` следует за фразой, House за которой ] не заменяется на второй итерации. Вы должны выровнять код с вашим описанием.

3. @Armali в обоих положительных значениях (просмотр сзади и в начале) есть пробел. (?<=<space here>|^|n)...(?=<space here>|$|.|,)

4. Я хорошо осведомлен о пробелах, и это не имеет ничего общего с тем, что я написал. Попробуйте опубликованный вами код, и вы увидите, что он не выполняет то, что вы описываете .

Ответ №1:

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

 ["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) . ")[amp;()'-]{0,1})(?= |$|.|,)/";

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

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

Вот демонстрация PHP.

Комментарии:

1. К сожалению, неприменимо. Таким образом, я не могу сопоставить эту случайную часть с определенной словарной записью — это не входит в цикл for :/ Но я попытаюсь использовать его с массивом assoc с предварительно сгенерированной случайной частью в качестве ключей и записями dict в качестве значений. Собираюсь опубликовать код, если это сработает.

Ответ №2:

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

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

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

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