Невозможно сопоставить регулярное выражение для любого символа, кроме ‘ и «

#javascript #regex

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

Вопрос:

Я написал регулярное выражение для сопоставления со строкой

{{AB.group.one}}:"eighth",{{AB.group.TWO}}:"third",{{attr1111}}:"fourth","fifth":{{attr_22_2qq2}},"sixth":{{AB.group.three}},{{ab.group.fourth}}:"seventh","ninth":{{attr1111}}}

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

/[^'"]({{2}[a-zA-Z0-9$_].*?}{2})[^'"]/gi

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

  • [^'"] : Начните с символа , который не является ни ' тем , ни " другим .
  • ({{2}[a-zA-Z0-9$_].*?}{2}) : Иметь ровно 2 {{ , затем любой символ в диапазоне a-zA-Z0-9$_ . После этого ровно 2 }}
  • [^'"] : Любой символ , кроме ' и " .

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

Ожидаемые совпадения:

  • {{AB.group.one}}
  • {{AB.group.TWO}}
  • {{attr1111}}
  • {{attr_22_2qq2}}
  • {{AB.group.three}}
  • {{ab.group.fourth}}
  • {{attr1111}}}

Результирующие совпадения:

  • {{AB.group.TWO}}
  • {{attr1111}}
  • {{attr_22_2qq2}}
  • {{AB.group.three}}
  • {{attr1111}}}

Как вы можете видеть на изображении ниже {{AB.group.one}} , {{ab.group.fourth}} они не совпадают. Я хочу, чтобы они тоже соответствовали им.

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

Я знаю причины, по которым они не совпадают.

Причина {{AB.group.one}} , по которой не совпадает, заключается в том, что [^'"] ожидается один символ, кроме ' и " , и я его не предоставляю. Если я заменю [^'"] на ["'"]* , это будет работать, но в этом случае "{{AB.group.one}}" тоже будет совпадать.

Итак, постановка задачи заключается в сопоставлении любого символа (если он есть) до {{ и после }} , но символ не может быть ' или " .

Причина {{ab.group.fourth}} , по которой не совпадает, заключается в том, что символ, предшествующий этому совпадению, т.Е. , Является частью другого совпадения. Это всего лишь мое предположение, причина может быть в чем-то другом. Но если я включу любой символ между {{AB.group.three}}, и {{ab.group.fourth}} (например {{AB.group.three}}, {{ab.group.fourth}} ), тогда шаблон совпадет. Я понятия не имею, как я могу это исправить.

Пожалуйста, помогите мне в решении этих двух проблем. Спасибо.

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

1. Нет, это не работает. Простым случаем несоответствия может быть {AB.group.one}} .

2.Возможно, так (?<![{'"]){{[a-zA-Z0-9$_].*?}}(?!['"}]) regex101.com/r/33jWcr/1

3. Идеально! Не могли бы вы написать это в ответе. Я установлю это как принятый ответ.

4. Кроме того, не могли бы вы объяснить, что (?<! здесь происходит?

Ответ №1:

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

 var input = "{{AB.group.one}}:"eighth",{{AB.group.TWO}}:"third",{{attr1111}}:"fourth","fifth":{{attr_22_2qq2}},"sixth":{{AB.group.three}},{{ab.group.fourth}}:"seventh","ninth":{{attr1111}}},"blah":"stuff",{{one}}:{{two}}";
var terms = input.replace(/".*?"/g, "").replace(/[,:] /g, ",").split(",");
console.log(terms); 

Ответ №2:

На самом деле вы были очень близки к тому, что у вас было.

 let input = '{{AB.group.one}}:"eighth",{{AB.group.TWO}}:"third",{{attr1111}}:"fourth","fifth":{{attr_22_2qq2}},"sixth":{{AB.group.three}},{{ab.group.fourth}}:"seventh","ninth":{{attr1111}}}'

let regex = /(?<=[^'"]?)({{2}[a-zA-Z0-9$_].*?}{2})(?=[^'"]?)/gi;

console.log(input.match(regex)) 

(?<=[^'"]?) это положительный взгляд назад. Поскольку используется отрицаемый набор символов, мы проверяем, что символ перед совпадением не является ‘ или «. Знак вопроса делает это необязательным — сопоставьте ноль или один из предыдущих токенов (отрицаемый набор символов).

(?=[^'"]?) является положительным прогнозом и проверяет токен сразу после выражения, чтобы убедиться, что это не «или » (или что после выражения нет токена).

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

 let input = '{{AB.group.one}}:"eighth",{{AB.group.TWO}}:"third",{{attr1111}}:"fourth","fifth":{{attr_22_2qq2}},"sixth":{{AB.group.three}},{{ab.group.fourth}}:"seventh","ninth":{{attr1111}}}'

let regex = /(?:[^{'"])?({{2}[a-zA-Z0-9$_].*?}{2})(?:[^}'"])?/gi

console.log([...input.matchAll(regex)].map(reg => reg[1])) 

String.match() теряет ссылку на группы захвата при передаче глобального флага, поэтому возвращает только «совпадение». Поскольку вы создаете группу захвата с ({{2}[a-zA-Z0-9$_].*?}{2}) помощью , если вы хотите просто убедиться, что символы, непосредственно окружающие выражение, заключенное в квадратные скобки, не являются кавычками, вы можете просто использовать группы без захвата для этих необязательных проверок.

(?:[^{'"])? является группой без захвата, как (?:[^}'"])?

Используя String.matchAll, первым элементом массивов, созданных для каждого совпадения, является полное совпадение, второй элемент — первая группа захвата и т.д. Таким образом, логика сопоставления [...input.matchAll(regex)] заключается в том, чтобы просто собирать группу захвата из каждого совпадения.