#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.