Как отформатировать и заменить группы с помощью RegEx (или, может быть, нет?) (Java)

output = output.replaceAll("%(\\w+)%",getVar("$1"));

public String getVar(name){...return formatted;}

У меня есть эта строка кода (в JAVA), и функция под названием getVar() это даст мне значение переменной с именем, которое мы хотим. Функция работает отлично, но этот код, похоже, больше не ищет группы.

Строка, которую я форматирую с помощью этого регулярного выражения:

"My name is %name% and I am %age% years old."

И вместо того, чтобы вернуть меня "My name is Paulo and I am 15 years old." (Так как name = Paulo а также age = 15) Это ничего мне не возвращает. Вместо замены регулярного выражения на getVar(name) или же getVar(age), он заменяет его getVar("$1"),

Есть ли какой-то способ исправить это, это ошибка или предполагаемое поведение? И если это так, как я могу получить тот же результат другим способом?

РЕДАКТИРОВАТЬ:

for(String i: varnames){
            output = output.replaceAll("%"+i+"%",getVar(i));
}

Работает ли для этого конкретного случая... Но все же, есть ли способ использовать функции внутри replaceAll() и поддержание групп (например, $1, $2) работает внутри функции?

РЕДАКТИРОВАТЬ 2:

//Variables//
    ArrayList<String> varnames = new ArrayList<String>(0);
    ArrayList<String> varvalues = new ArrayList<String>(0);
//end of Variables

private String getVar(String name){
    String returnv = "";
    if(varnames.contains(name.toLowerCase())) returnv = varvalues.get(varnames.indexOf(name.toLowerCase()));
    //System.out.println("\n\n"+name+"\n\n");
    return returnv;
}

private String format(String input){
    String output = input;

    output = output.replace("[br]","/n");  

    for(String i: varnames){
        output = output.replaceAll("%"+i+"%",getVar(i));//This is how I am parsing the variables.
    }

    //Here I want to handle inline functions... for example: a function called 'invert' that would switch the letters. If the input String that is being formatted (output) contains the regex, the function needs to evaluate and replace.

    //How I tried to do it:
    output.replaceAll("invert\((\w+)\)",invertLetters("$1"));

        return output;
    }

public String invertLetters(String input){//Inverts the letters of the String}

1 ответ

Решение

Как уже упоминалось, codisfy не совсем понятно, если вы говорите о java или же javascript, как вы используете replaceAll метод я буду считать, что вы используете java, Однако то, что я объясню ниже, действительно для большинства (если не для всех) систем регулярных выражений независимо от языка программирования.

Когда вы звоните outputString=inputString.replaceAll("REGEX","REPLACEMENT"); метод replaceAll настроит свой внутренний движок регулярных выражений, построит конечный автомат (для простоты, давайте опустим разницу между DFA / NFA здесь) с регулярным выражением, переданным в качестве параметра и проанализировать inputString на котором он вызывается для того, чтобы сделать замену и вернуть результат (outputString).

Когда метод вызывается, он также нуждается в замене String (REPLACEMENT) это обычная строка, которая может содержать или не содержать обратных ссылок на некоторые группы, чтобы включить некоторую контекстную замену (используя синтаксис $1, $2 или же \1, \2... в зависимости от языка).

Что очень важно понять, это то, что и регулярное выражение, и его замещающая строка являются простыми строками, не имеющими особого значения вне механизма регулярных выражений (метод replaceAll).

Следовательно, если вы повторно используете их в других методах (например, передавая их в качестве параметров), они будут интерпретироваться literally как и в случае с другими обычными строками.

Так что не ожидайте, что $1 заменяется name или же age в вашем звонке getVar("$1"), Это будет просто $1 и ничего больше.

Кроме того, как говорится, ваш метод public void getVar(name){...} даже не возвращает строку, так как ее тип возврата void, как следствие, если вы код в java и если вы используете replaceAll метод класса String (который ожидает 2 строки в качестве аргументов), он даже НЕ будет компилироваться в первую очередь.

Я позволю вам реализовать остальную часть кода, но если вы измените цикл замены следующим образом, он должен работать:

String input="My name is %name% and I am %age% years old.";
Matcher matcher = Pattern.compile("%(\\w+)%").matcher(input);
String output=new String(input);
while (matcher.find()) {
          System.out.println("------------------------------------");
          System.out.println("Back reference:" + matcher.group(1));
          String group=matcher.group(1);//give access to the first matching group so that it can be reused
          output=output.replaceAll("%"+group+"%", getVar(group));
       }

System.out.println(output);

getVar код метода: (я позволю вам адаптировать его)

public static String getVar(String name){ 
    if(name.equals("name"))
        return "Paulo"; 
    return "15"; 
}

ВЫХОД:

------------------------------------
Back reference:name
------------------------------------
Back reference:age
My name is Paulo and I am 15 years old.
Другие вопросы по тегам