2016-07-28 17 views
1

Groovy здесь. Я даться String с GString- стиль переменные в нем, как:Groovy regex PatternSyntaxException при разборе переменных в стиле GString

String target = 'How now brown ${animal}. The ${role} has oddly-shaped ${bodyPart}.' 

Имейте в виду, это не предназначен для использования в качестве фактического GSTRING !!! То есть, у меня не будет 3 строковых переменных (animal, role и bodyPart соответственно), которые Groovy будет решать во время выполнения. Вместо, я ищу, чтобы сделать 2 разные вещи, чтобы эти «целевые» строки:

  • Я хочу, чтобы быть в состоянии найти все экземпляры этих переменных рефов ("${*}") в целевой строке, и заменить его с ?; и
  • мне нужно найти все экземпляры этих переменных рефов и получить список (позволяющие простофили) с их именами (что в приведенном выше примере, будет [animal,role,bodyPart])

Моя лучшая попытка до сих пор:

class TargetStringUtils { 
    private static final String VARIABLE_PATTERN = "\${*}" 

    // Example input: 'How now brown ${animal}. The ${role} has oddly-shaped ${bodyPart}.' 
    // Example desired output: 'How now brown ?. The ? has oddly-shaped ?.' 
    static String replaceVarsWithQuestionMarks(String target) { 
     target.replaceAll(VARIABLE_PATTERN, '?') 
    } 

    // Example input: 'How now brown ${animal}. The ${role} has oddly-shaped ${bodyPart}.' 
    // Example desired output: [animal,role,bodyPart] } list of strings 
    static List<String> collectVariableRefs(String target) { 
     target.findAll(VARIABLE_PATTERN) 
    } 
} 

... PatternSytaxException производит в любое время, когда я иду, чтобы запустить любой метод:

Exception in thread "main" java.util.regex.PatternSyntaxException: Illegal repetition near index 0 
${*} 
^ 

Любые идеи, где я собираюсь наперекосяк?

+1

Использование 'Строка VARIABLE_PATTERN =/\ $ \ {([^ {}] *) \} /' –

+0

Спасибо @ WiktorStribiżew (+1), который решает исключение, но 'collectVariableRefs (...)' теперь возвращает '[$ {animal}, $ {role}, $ {bodyPart}]', тогда как я ищу '[animal, role, bodyPart]' ... любые идеи? – smeeb

+0

Вам нужно просто захватить значения группы захвата # 1. –

ответ

1

Вопрос заключается в том, что вы не избежала шаблон правильно, и findAll будет собирать только все матчи, в то время как вам нужно захвата подмаски внутри {}.

Использование

def target = 'How now brown ${animal}. The ${role} has oddly-shaped ${bodyPart}.' 
println target.replaceAll(/\$\{([^{}]*)\}/, '?') // => How now brown ?. The ? has oddly-shaped ?. 

def lst = new ArrayList<>(); 
def m = target =~ /\$\{([^{}]*)\}/ 
(0..<m.count).each { lst.add(m[it][1]) } 
println lst // => [animal, role, bodyPart] 

См this Groovy demo

Внутри /\$\{([^{}]*)\}/ slashy строки, вы можете использовать одинарные обратные слэши, чтобы избежать специальных регулярных выражений метасимволы, и весь шаблон регулярного выражения выглядит чище.

  • \$ - будет соответствовать буквальное $
  • \{ - будет соответствовать буквальное {
  • ([^{}]*) - Группа 1 захватывая любые символы, отличные от { и }, 0 или более раз
  • \} - литерал }.
+0

Этот фрагмент кода является грубым кодом, но он показывает основное направление. –