Я думаю, что ваш оригинальный подход \${(.*)}
имеет небольшую проблему, заключающуюся в том, что ваш подстановочный сопоставитель .*
содержит символ }
, который вы не хотите сопоставлять. Фактически, как только вы начинаете захват, это единственное, что вы не хотите сопоставлять, поэтому мы меняем:
.* // match anything zero or more times
до
[^}]* // match anything that isn't } zero or more times
Но вы хотите сопоставить все в фигурных скобках, если у него нет структуры some_underscored_words:(desired-text)
, в этом случае вы хотите сопоставить desired-text
.
Я бы решил эту проблему, используя оператор ?
, который вы помещаете после группы захвата, чтобы определить его как необязательный. ?
является жадным, что означает, что он сначала попытается сопоставить, и только в случае неудачи попытается обработать совпадения без дополнительного шаблона.
Чтобы подумать об этом, полезно перефразировать то, что вы хотите, используя жадное мышление.
Вместо того чтобы сказать:
Я хочу захватить все, что находится внутри фигурных скобок, а также
захватить значение в скобках, если они существуют
Измените его на:
Я хочу захватить значение, которое вложено в скобки
внутри фигурных скобок, но если этого не будет, я просто буду
все, что находится внутри брекетов.
Превращая это в регулярное выражение, я получаю это:
\${([a-z_]+:\()?([^\)}]*)
Разбивка:
Начните с поиска уникального символа:
${
Попробуйте сопоставить с вложенным шаблоном:
([a-z_]+:\()?
Это соответствует any_underscored_lowercase_words
один или несколько раз (+
), за которыми следует :(
Теперь мы сопоставляем ноль или более букв, которые не являются ни нашими закрывающими тегами )
или }
([^\)}]*)
Будучи жадным, он идет прямо к вложенному шаблону. В противном случае совпадение сводится к захвату всего, что не является ни одним из закрывающих символов.
Один сценарий, который я могу придумать, где это не сработает, это:
${seems like a normal match) wait where did these letters go?}
Что даст вам "похоже на нормальное совпадение".