Javascript Regex — захват только неэкранированных шаблонов

Учитывая строку в Javascript, например

{включать} что-либо в {фигурные скобки}, но не тогда, когда они экранированы, как {это}, и работают для любой позиции {скобки}

я хочу получить

  • включать
  • фигурные скобки
  • скобка

Я пытался найти способ, но, не оглядываясь назад, я в тупике.

Самое главное - НЕ получать экранированное содержимое {}. Я был бы в порядке с чем-то, что включает фигурные скобки в матчах, если это необходимо.

К сожалению, все, что мне удалось до сих пор, это выражение, подобное этому

(?:[^//]){.*?}

Но это не соответствует, если { находится в начале целевого текста.

Может кто-нибудь помочь мне? Спасибо.


person Toby    schedule 18.01.2017    source источник
comment
Он экранирован с помощью \ или /?   -  person Wiktor Stribiżew    schedule 18.01.2017
comment
Извините - опечатка escape char. Обновлены   -  person Toby    schedule 18.01.2017
comment
Итак, это все еще /? :) Если нет, вам нужно будет использовать \\ в регулярном выражении, которое я предлагаю вместо \/.   -  person Wiktor Stribiżew    schedule 18.01.2017


Ответы (1)


Я предполагаю, что escape-символ /.

Вы можете использовать следующее регулярное выражение с группой захвата, которая будет содержать ваши значения:

/(?:^|[^\/]){([^}]*)}/g
             ^^^^^^^

См. демонстрацию регулярного выражения.

Подробности:

  • (?:^|[^\/]) - либо начало строки, либо символ, отличный от /
  • { - буквальное {
  • ([^}]*) — Группа 1 захватывает любые символы 0+, отличные от } (добавьте { в класс, чтобы соответствовать кратчайшему окну между { и })
  • } - буквальное }.

var rx = /(?:^|[^\/]){([^}]*)}/g;
var str = "{include} anything in {curly braces} but not when they are escaped like /{this} and work for any position of the {brace}";
var m, res = [];
while ((m = rx.exec(str)) !== null) {
  res.push(m[1]);
}
console.log(res);

person Wiktor Stribiżew    schedule 18.01.2017
comment
Если у вас есть \ в качестве escape-символа, вам нужно изменить [^\/] на [^\\]. - person Wiktor Stribiżew; 18.01.2017
comment
Спасибо Виктор. Это, безусловно, будет работать для меня. Я могу запустить некоторый код, чтобы обрезать вывод. Я не очень силен в регулярных выражениях Javascript, но из интереса, в чем разница между вашим способом и просто этим? ([^\/]|^){.*?} Я действительно не понимаю влияния ?: или почему ([^}]*) вместо просто .*? - Я предполагаю, что есть что-то, что мне не хватает, и мне интересно узнать. Спасибо - person Toby; 18.01.2017
comment
{.*?} будет соответствовать {, 0+ символов, отличных от символов разрыва строки, как можно меньше до первого } (таким образом, он будет соответствовать строкам, которые находятся в одной строке). Кроме того, ленивый *? заставит char совпадать с char, что замедляет все это. С {[^}]*} вы сопоставляете {, любые символы 0+, отличные от }, жадно, как можно больше, вплоть до первого } (так что, даже если внутри есть разрывы строк, они будут сопоставлены). Поскольку сопоставление является жадным, скорость сопоставления здесь намного выше. Лучше всего: если вы можете избавиться от .* / .*? в шаблоне, замените их более точным эквивалентом. - person Wiktor Stribiżew; 18.01.2017
comment
Действительно полезно. Большое спасибо. - person Toby; 18.01.2017
comment
Это не будет работать для последующих шаблонов, таких как {a}{b}. Только {a} будет соответствовать. - person David Bonnet; 24.07.2017
comment
@DavidBonnet Да, для таких перекрывающихся совпадений вы не можете не использовать не потребляющий шаблон. Я предлагаю инвертировать строку, чтобы вы могли использовать шаблон с просмотром вперед вместо просмотра назад, а также инвертировать все совпадения. См. эту JSFiddle. - person Wiktor Stribiżew; 24.07.2017