Как исключить текст между двумя фигурными скобками с помощью регулярного выражения?

Я новичок в регулярных выражениях, у меня есть такой текст:

test{{это не следует выбирать и фигурные скобки тоже}}, но следует выбрать этот { или }. Поэтому я хочу исключить весь текст между открывающей и закрывающей фигурными скобками.

и я хочу этот результат

"тестовое задание"

а также

«но этот { или } должен быть выбран. Поэтому я хочу исключить весь текст между открывающей и закрывающей фигурными скобками».

Это мое выражение, которое я использовал:

$p = '/[a-zA-Z0-9#\' ]+(?![^{{]*}})/';

Но это исключает одиночные фигурные скобки.
Я хочу знать, как включить одиночные фигурные скобки в текст и исключить только текст между двумя фигурными скобками
И, пожалуйста, не могли бы вы дать мне хорошую документацию о выражении регулярного выражения? Я хочу узнать больше об этом.


person Mana    schedule 03.06.2017    source источник
comment
разделить текст с помощью preg_split   -  person Casimir et Hippolyte    schedule 03.06.2017
comment
Очень странная задача. '~{{.*?}}(*SKIP)(*F)|(?:(?!{{.*?}}).)+~s должно работать.   -  person Wiktor Stribiżew    schedule 03.06.2017


Ответы (4)


Ввод (для эффекта я удвоил строку):

$string = 'test{{this should not be selected and the curly brackets too}} but this one { or } should be selected. So I want to exclude all text between an opening and closing curly brackets. test{{this should not be selected and the curly brackets too}} but this one { or } should be selected. So I want to exclude all text between an opening and closing curly brackets.';

Способ №1 preg_split():

var_export(preg_split('/{{[^}]*}}/', $string, 0, PREG_SPLIT_NO_EMPTY));
// Added the fourth param in case the input started/ended with a double curly substring.

Способ №2 preg_match_all():

var_export(preg_match_all('/(?<=}{2}|^)(?!{{2}).*?(?={{2}|$)/s', $string, $out) ? $out[0] : []);

Выход (в любом случае):

array (
  0 => 'test',
  1 => ' but this one { or } should be selected. So I want to exclude all text between an opening and closing curly brackets. test',
  2 => ' but this one { or } should be selected. So I want to exclude all text between an opening and closing curly brackets.',
)

preg_split() рассматривает подстроки с двойной фигурной оберткой как разделители и разбивает на них полную строку.


Шаблон метода preg_match_all()... Демонстрация шаблона. которые охотятся за двойными завитками или началом/концом строки. Он использует отрицательный поиск в середине, чтобы избежать сопоставления нежелательных строк с двойным изгибом в начале новой строки. Наконец, модификатор s в конце шаблона позволит . соответствовать символам новой строки.

person mickmackusa    schedule 03.06.2017
comment
Не уверен, что хочет присоединиться к разным частям (см. вопрос). - person Casimir et Hippolyte; 03.06.2017
comment
@Mana Ты тоже доволен версией preg_match_all? кажется, ты действительно этого хочешь. Когда вы тестируете свои шаблоны, используйте regex101.com, потому что он сообщает вам, когда у вас есть синтаксическая ошибка, и объясняет, что такое ваш шаблон. делает. regular-expressions.info — хорошее место, чтобы ознакомиться с информацией. - person mickmackusa; 03.06.2017
comment
@Mana Помимо этих веб-сайтов, конечно, есть много других очень ценных сайтов. Честно говоря, все эти инструкции начинают превращать ваш мозг в кашу, если вы смотрите на них слишком долго; если вы хотите, чтобы регулярное выражение действительно укоренилось, попрактикуйтесь в реальных ситуациях. Вопросы SO сотворили чудеса для моего понимания регулярных выражений. Если вы хотите, чтобы я порекомендовал вам каких-нибудь безумно крутых пользователей SO, начните с: Wiktor Stribiżew и Casimir et Hippolyte. Я никогда, никогда не видел, чтобы эти парни забивались в тупик, и они знают кучу трюков. - person mickmackusa; 03.06.2017
comment
@Mana Я проверил все шаблоны, опубликованные в настоящее время на этой странице, и, хотя многие из них верны, ни один из них не является более эффективным (с точки зрения шагов). Поскольку ваша цель — самообразование, вы должны попытаться понять их все. Другими соображениями метода являются краткость шаблона, а также размер вывода. При использовании групп захвата выходной массив увеличивается как минимум на 100%, я бы посоветовал вам всегда искать шаблон без захвата, когда это возможно. - person mickmackusa; 04.06.2017

(?:^|(?:}}))(.+?)(?:$|{{)

Попробуйте: https://regex101.com/r/2Xy7gU/1/
Что здесь происходит:

  • (?:^|(?:}})) - начинается либо с начала строки, либо с }}
  • (.+?) - соответствует всему (нежадный)
  • (?:$|{{) - совпадение должно заканчиваться либо концом строки, либо {{

То, что вы хотите (без скобок), находится в первой группе.

person ja2142    schedule 03.06.2017
comment
Я также хочу исключить две скобки, иначе есть ли какое-либо решение для несоответствия текста, если оно находится только между открывающими и закрывающими скобками. Потому что я только что проверил ваше решение и кажется, что оно не будет соответствовать тексту, если найдет две открывающие скобки, попробуйте этот текст, чтобы понять, что я имею в виду: test{{это не должно быть выбрано и фигурные скобки тоже}} но это o}}ne { или } должно быть выбрано. Поэтому я хочу исключить весь текст между {{открывающими и закрывающими фигурными скобками. - person Mana; 03.06.2017
comment
Мое решение работает, если скобки совпадают (одинаковое количество открывающих и закрывающих) и если они не вложены друг в друга. Если вы хотите, чтобы это работало для более сложной группировки, вы можете выполнить поиск {{ и }} и исключить совпадения, включающие указанные группы. - person ja2142; 03.06.2017
comment
Или вы можете просто вставить отрицательный прогноз: (?:^|(?:}}))((?:(?!}}).)+?)(?:$|{{) regex101.com/r/44DDqO/1 Это что вам нужно? - person ja2142; 04.06.2017

Используйте preg_replace и замените все вхождения \{\{[^\}]*\}\} пустой строкой.

Пример: http://www.regextester.com/?fam=97777.

Объяснение:

\{      - {
\{      - {
[^\}]*  - everything except }
\}      - }
\}      - }
person Adam    schedule 03.06.2017
comment
Мне нужно использовать preg_match_all и получить фрагмент текста, который не находится внутри двух фигурных скобок. есть ли способ использовать отрицание с вашим решением? - person Mana; 03.06.2017

2 варианта:

  • легко: просто рассмотрите блоки между {{ }} как шаблон разделения
    $validblocks = preg_split("/{{[\w .]+}}/", $str);
  • сложно: используй группы и сначала зафиксируй отклоненный паттерн, потом что останется:
    (?<novalid>{{[\w ]+}})|(?<valid>{|[\w .]*|})
    управляй потом как хочешь. Пример здесь: https://regex101.com/r/SK729o/2
person mquantin    schedule 03.06.2017