#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/13. Идеально! Не могли бы вы написать это в ответе. Я установлю это как принятый ответ.
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)]
заключается в том, чтобы просто собирать группу захвата из каждого совпадения.