Возникала необходимость сформировать строку на заданному шаблону. Причем очень срочно
Т.к. времени изобретать велосипед нет, а в инете быстро найти не удалось, прошу подсказать как реализуется подобное.
Требуется следующее:
String strtemplate = "Пользователь %name%, возраст %age% лет";
String name = "Вася";
int age = 25;
Необходимо получить строку:
str = "Пользователь Вася, возраст 25 лет";
Пример кода можно на C/C++ или Pascal. Но если будет на Java то ваще супер
Здравствуйте, C0s, Вы писали:
C0s>Здравствуйте, Eugene Novikov, Вы писали:
C0s>
EN>String strtemplate = "Пользователь %name%, возраст %age% лет";
C0s>а формат шаблона только такой или примерно такой?
EN>>Пример кода можно на C/C++ или Pascal. Но если будет на Java то ваще супер
C0s>
String.format("Пользователь %1$s, возраст %2$d лет", "Вася", Integer.valueOf(25))
Нее, мне не так надо. Реально в программу передается шаблон строки и там как угодно могут стоять переменные типа %value%. И нужно именно используя шаблон, как то его распарсить, и вставить нужные реальные величины. А шаблон я привел ваще с потолка. Реально там может быть что угодно. Мне нужен именно алгоритм как в шаблоне найти заданное место куда вставить соответствующие значения.
Здравствуйте, Eugene Novikov, Вы писали:
EN>Нее, мне не так надо. Реально в программу передается шаблон строки и там как угодно могут стоять переменные типа %value%. И нужно именно используя шаблон, как то его распарсить, и вставить нужные реальные величины. А шаблон я привел ваще с потолка. Реально там может быть что угодно. Мне нужен именно алгоритм как в шаблоне найти заданное место куда вставить соответствующие значения.
я не уверен, что точно понимаю смысл написанного
я к тому, что синтаксис шаблона надо зафиксировать, и лучше это делать, исходя из имеющихся библиотечных возможностей (ясно, что String.format — это слишком просто, но бывают движки и помощнее, типа velocity/freemarker или mvel templates). кроме синтаксиса, надо и возможный список имён переменных тоже зафиксировать — набор их значений всегда будет передаваться в вызов подстановщика
Здравствуйте, C0s, Вы писали:
C0s>Здравствуйте, Eugene Novikov, Вы писали:
EN>>Нее, мне не так надо. Реально в программу передается шаблон строки и там как угодно могут стоять переменные типа %value%. И нужно именно используя шаблон, как то его распарсить, и вставить нужные реальные величины. А шаблон я привел ваще с потолка. Реально там может быть что угодно. Мне нужен именно алгоритм как в шаблоне найти заданное место куда вставить соответствующие значения.
C0s>я не уверен, что точно понимаю смысл написанного
C0s>я к тому, что синтаксис шаблона надо зафиксировать, и лучше это делать, исходя из имеющихся библиотечных возможностей (ясно, что String.format — это слишком просто, но бывают движки и помощнее, типа velocity/freemarker или mvel templates). кроме синтаксиса, надо и возможный список имён переменных тоже зафиксировать — набор их значений всегда будет передаваться в вызов подстановщика
Да, имена переменных будут фиксированными, но вот то что шаблон будет фиксированным это вряд ли. Я то бы только "за", мне бы проще было. Но там такая ситуация, что хотят задавать шаблоны для SMS сообщений, в которые надо подставлять данные считанные с приборов. Например: "Напряжение на входе %AI0% вольт" , и мне надо вычислить что надо подставить значение с 0-го входа. Но могут и по другому сформировать сообщение, например добавить в него еще переменных, или поставить %AI0% в другое место.
Мне надо что то из серии как в винде переменные окружения задаются типа %SystemRoot%\system32 что на самом деле означает C:\Windows\system32. Там же шаблон не фиксирован и можно где угодно вставлять этот %SystemRoot%
Мощные движки мне тоже не подойдут, т.к. крутится все это на Java2ME.
Здравствуйте, Eugene Novikov, Вы писали:
EN>Да, имена переменных будут фиксированными, но вот то что шаблон будет фиксированным это вряд ли. Я то бы только "за", мне бы проще было. Но там такая ситуация, что хотят задавать шаблоны для SMS сообщений, в которые надо подставлять данные считанные с приборов. Например: "Напряжение на входе %AI0% вольт" , и мне надо вычислить что надо подставить значение с 0-го входа. Но могут и по другому сформировать сообщение, например добавить в него еще переменных, или поставить %AI0% в другое место.
EN>Мощные движки мне тоже не подойдут, т.к. крутится все это на Java2ME.
тогда String.format подойдёт — вместо имён фиксируйте позиции переменных, а тот, кто будет задавать тексты реальных шаблонов пусть выучит синтаксис java.util.Formatter
Здравствуйте, Eugene Novikov, Вы писали:
EN>Мощные движки мне тоже не подойдут, т.к. крутится все это на Java2ME.
а вот если нужны lazy-вычисления, например, если список зафиксированных переменных слишком велик, и вычислять его каждый раз при вызове вычисления конечной строки полностью накладно, то тогда советую посмотреть на mvel templates, можно будет создать класс с геттерами, каждый отвечает за вычисление своей переменной, при вычислении результата по шаблону движок вызовет только указанные в исходном тексте строки геттеры
объём библиотеки небольшой (около 700K), надеюсь для jme это годится
Здравствуйте, C0s, Вы писали:
C0s>Здравствуйте, Eugene Novikov, Вы писали:
EN>>Да, имена переменных будут фиксированными, но вот то что шаблон будет фиксированным это вряд ли. Я то бы только "за", мне бы проще было. Но там такая ситуация, что хотят задавать шаблоны для SMS сообщений, в которые надо подставлять данные считанные с приборов. Например: "Напряжение на входе %AI0% вольт" , и мне надо вычислить что надо подставить значение с 0-го входа. Но могут и по другому сформировать сообщение, например добавить в него еще переменных, или поставить %AI0% в другое место.
EN>>Мощные движки мне тоже не подойдут, т.к. крутится все это на Java2ME.
C0s>тогда String.format подойдёт — вместо имён фиксируйте позиции переменных, а тот, кто будет задавать тексты реальных шаблонов пусть выучит синтаксис java.util.Formatter
Ну даже если использовать String.format, мне все равно не понятно как это будет выглядеть в случае моего примера:
String strtemplate = "Пользователь %name%, возраст %age% лет";
String name = "Вася";
int age = 25;
Мне надо чтобы переменная strtemplate использовалась, т.к. ее значение считывается с xml файла. Мне не нужен просто захардкоденый вариант строки, где в нужное место подставляются только переменные name и age. Шаблон задаю не я, а пользователь в конфигураторе.
Здравствуйте, C0s, Вы писали:
C0s>Здравствуйте, Eugene Novikov, Вы писали:
EN>>Мощные движки мне тоже не подойдут, т.к. крутится все это на Java2ME.
C0s>а вот если нужны lazy-вычисления, например, если список зафиксированных переменных слишком велик, и вычислять его каждый раз при вызове вычисления конечной строки полностью накладно, то тогда советую посмотреть на mvel templates, можно будет создать класс с геттерами, каждый отвечает за вычисление своей переменной, при вычислении результата по шаблону движок вызовет только указанные в исходном тексте строки геттеры
C0s>объём библиотеки небольшой (около 700K), надеюсь для jme это годится
Неужели все так сложно? Фигово дело, если нет достаточно простого механизма для таких дел Либо Вы все таки не до конца поняли, что мне нужно в конечном итоге.
Здравствуйте, Eugene Novikov, Вы писали:
EN>Ну даже если использовать String.format, мне все равно не понятно как это будет выглядеть в случае моего примера:
1) фиксируется и согласуется с настройщиками шаблонов список переменных по позициям
имя — 1
возраст — 2
напряжение в вольтах — 3
<...>
2) где-то вовне задаются шаблоны согласно синтаксису Formatter'а,
т.е. "Пользователь %1$s, возраст %2$d лет"
или "%2$d-ний пользователь %1$s"
или "Зафиксировано напряжение %3$d в голове пользователя '%1$s'"
или ещё как-то
3) в программе в момент вычисления строки:
final Object[] templateParams = { currentUserName, currentUserAge, voltage, .... };
final String template = // приходит из конфигурации сообщенийfinal String result = String.format(template, templateParams);
тот факт, что здесь надо сразу подставлять все вычисленные значения, и нет возможности сделать lazy-вычисления — может являться минусом, зависит от стоимости вычислений.
Здравствуйте, C0s, Вы писали:
C0s>Здравствуйте, Eugene Novikov, Вы писали:
EN>>Ну даже если использовать String.format, мне все равно не понятно как это будет выглядеть в случае моего примера:
C0s>1) фиксируется и согласуется с настройщиками шаблонов список переменных по позициям C0s>имя — 1 C0s>возраст — 2 C0s>напряжение в вольтах — 3 C0s><...>
C0s>2) где-то вовне задаются шаблоны согласно синтаксису Formatter'а, C0s>т.е. "Пользователь %1$s, возраст %2$d лет" C0s>или "%2$d-ний пользователь %1$s" C0s>или "Зафиксировано напряжение %3$d в голове пользователя '%1$s'" C0s>или ещё как-то
C0s>3) в программе в момент вычисления строки: C0s>
C0s>final Object[] templateParams = { currentUserName, currentUserAge, voltage, .... };
C0s>final String template = // приходит из конфигурации сообщений
C0s>final String result = String.format(template, templateParams);
C0s>
C0s>тот факт, что здесь надо сразу подставлять все вычисленные значения, и нет возможности сделать lazy-вычисления — может являться минусом, зависит от стоимости вычислений.
Map <String, String> values = ...; // Имя переменной -> значение
Pattern p = Pattern.compile("%(\\w+)%");
Matcher m = p.matcher("Пользователь %name%, возраст %age% лет");
StringBuffer sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, values.get(m.group(1)));
}
m.appendTail(sb);
// Готово
System.out.println(sb.toString());
EN>> Т.е. мне сначала надо узнать какие именно данные подставлять. Я вот подумал, может регулярные выражения тут подойдут?
BC>Легко. BC>Смотрим сюда и делаем, как в примере
BC>
BC>Map <String, String> values = ...; // Имя переменной -> значение
BC>Pattern p = Pattern.compile("%(\\w+)%");
BC> Matcher m = p.matcher("Пользователь %name%, возраст %age% лет");
BC> StringBuffer sb = new StringBuffer();
BC> while (m.find()) {
BC> m.appendReplacement(sb, values.get(m.group(1)));
BC> }
BC> m.appendTail(sb);
BC>// Готово
BC> System.out.println(sb.toString());
BC>
Спасибо, очень похоже на то что мне надо, только с некоторым допиливанием. У меня заранее известны только возможные имена переменных. Значения постоянно меняются и нужно в момент запроса подставить текущее значение.
т.е. имеем:
int dv[] = new int[9];
float av[] = new float[2];
данные в этих массивах постоянно меняются. В момент запроса по шаблону:
String temlate = "dv = %dv2%, av = %av1%";
получить нужную строку. Т.е. надо выудить %dv2% и %av1%, распарсить и подставить соотвествующие значения dv[2] и av[1].
Здравствуйте, LeonidV, Вы писали:
LV>У вас заранее заменяемые параметры не известны? Как вы тогда будете рассчитывать их значения?
Есть фиксированные возможные имена заменяемых параметров которые могут быть использованы.
int dv[] = new int[9];
float av[] = new float[2];
Т.е. поставляться могут только 9 параметров типа %dv1%, %dv2%, %dv3% ... %dv9% и 2 параметра типа %av1%, %av2%
Из шаблона надо получить этот параметр, разобрать и подставить нужное значение из соответствующего массива. Причем вид параметров в шаблоне может быть любой, например не %dv1% а %dv[1]%, главное чтобы можно было проще разобрать и подставить нужную текущую величину.
Здравствуйте, Eugene Novikov.
Вы писали:
EN> Спасибо, очень похоже на то что мне надо, только с некоторым допиливанием. У меня заранее известны только возможные имена переменных. Значения постоянно меняются и нужно в момент запроса подставить текущее значение. EN> т.е. имеем: EN>
EN> int dv[] = new int[9];
EN> float av[] = new float[2];
EN>
EN> данные в этих массивах постоянно меняются. В момент запроса по шаблону: EN>
Здравствуйте, xBlackCat, Вы писали:
BC>Здравствуйте, Eugene Novikov. BC>Вы писали:
EN>> Спасибо, очень похоже на то что мне надо, только с некоторым допиливанием. У меня заранее известны только возможные имена переменных. Значения постоянно меняются и нужно в момент запроса подставить текущее значение. EN>> т.е. имеем: EN>>
EN>> int dv[] = new int[9];
EN>> float av[] = new float[2];
EN>>
EN>> данные в этих массивах постоянно меняются. В момент запроса по шаблону: EN>>
EN>> получить нужную строку. Т.е. надо выудить %dv2% и %av1%, распарсить и подставить соотвествующие значения dv[2] и av[1].
BC>Тоже легко. Меняем шаблон на
"%(\\w+?)(\\d+)%"
BC>и меняем получение значения — делаем его зависимым от двух параметров: BC>
BC>m.appendReplacement(sb, getValue(m.group(1), m.group(2)));
BC>// ....
BC>String getValue(String name, String idx) {
BC> int index = Integer.parseInt(idx);
BC>// ....
BC>}
BC>
Здравствуйте, xBlackCat, Вы писали:
BC>Здравствуйте, Eugene Novikov. BC>Вы писали:
EN>> Спасибо, очень похоже на то что мне надо, только с некоторым допиливанием. У меня заранее известны только возможные имена переменных. Значения постоянно меняются и нужно в момент запроса подставить текущее значение. EN>> т.е. имеем: EN>>
EN>> int dv[] = new int[9];
EN>> float av[] = new float[2];
EN>>
EN>> данные в этих массивах постоянно меняются. В момент запроса по шаблону: EN>>
EN>> получить нужную строку. Т.е. надо выудить %dv2% и %av1%, распарсить и подставить соотвествующие значения dv[2] и av[1].
BC>Тоже легко. Меняем шаблон на
"%(\\w+?)(\\d+)%"
BC>и меняем получение значения — делаем его зависимым от двух параметров: BC>
BC>m.appendReplacement(sb, getValue(m.group(1), m.group(2)));
BC>// ....
BC>String getValue(String name, String idx) {
BC> int index = Integer.parseInt(idx);
BC>// ....
BC>}
BC>
Вот попадос то . Оказывается в Java2ME нет штатной либы для работы с regexp. Надыбал какой то Regexp-me, придется с ним разбираться и притягивать их функции. Надеюсь получится сделать так, как вы описали.
Здравствуйте, Eugene Novikov, Вы писали: EN>Вот попадос то . Оказывается в Java2ME нет штатной либы для работы с regexp. Надыбал какой то Regexp-me, придется с ним разбираться и притягивать их функции. Надеюсь получится сделать так, как вы описали.
Не надо там регэкспы, пожалейте пользователей с GPRS.
1. Ищете первый %, всё, что до него, выводите.
2. Ищете следующий %, выбираете имя между ними и подставляете.
3. Повторяете с п.1.
4. Если % кончились, просто выводите остаток.
Обработку ошибок и специальных случаев добавить по вкусу (как и с регэкспами).
Здравствуйте, gegMOPO4, Вы писали:
MOP>Здравствуйте, Eugene Novikov, Вы писали: EN>>Вот попадос то . Оказывается в Java2ME нет штатной либы для работы с regexp. Надыбал какой то Regexp-me, придется с ним разбираться и притягивать их функции. Надеюсь получится сделать так, как вы описали.
MOP>Не надо там регэкспы, пожалейте пользователей с GPRS.
MOP>1. Ищете первый %, всё, что до него, выводите. MOP>2. Ищете следующий %, выбираете имя между ними и подставляете. MOP>3. Повторяете с п.1. MOP>4. Если % кончились, просто выводите остаток.
MOP>Обработку ошибок и специальных случаев добавить по вкусу (как и с регэкспами).
На Си (на котором я в основном программирую), так бы и сделал. Но в Java подумал можно как то более элегантно это сделать. Фик знает че уже делать, ум на раскоряку. На Си мне проще, я там у меня опыт достаточно большой. А опыт в Java крайне маленький вот и думаю как тут лучше строки парсить.
Здравствуйте, Eugene Novikov, Вы писали: EN>На Си (на котором я в основном программирую), так бы и сделал. Но в Java подумал можно как то более элегантно это сделать. Фик знает че уже делать, ум на раскоряку. На Си мне проще, я там у меня опыт достаточно большой. А опыт в Java крайне маленький вот и думаю как тут лучше строки парсить.
Не нужно делать сложно то, что можно сделать просто. Готового стандартного лёгкого решения с именованными параметрами (да ещё и с индексами, как вы хотите), нет, задача несложна. Вручную всё сделать — будет, может, на десяток строк больше, чем с регэкспами или какой-то общей библиотекой (и на сотню килобайт легче).
Здравствуйте, gegMOPO4, Вы писали:
MOP>Здравствуйте, Eugene Novikov, Вы писали: EN>>На Си (на котором я в основном программирую), так бы и сделал. Но в Java подумал можно как то более элегантно это сделать. Фик знает че уже делать, ум на раскоряку. На Си мне проще, я там у меня опыт достаточно большой. А опыт в Java крайне маленький вот и думаю как тут лучше строки парсить.
MOP>Не нужно делать сложно то, что можно сделать просто. Готового стандартного лёгкого решения с именованными параметрами (да ещё и с индексами, как вы хотите), нет, задача несложна. Вручную всё сделать — будет, может, на десяток строк больше, чем с регэкспами или какой-то общей библиотекой (и на сотню килобайт легче).
Вся проблема в сроках. Если бы была куча времени, я бы спокойно свой парсер написал. А щас мне уже не очень важно на сколько "тяжелее" станет прога из-за сторонних библиотек, главное это скорость реализации нужного функционала. Будет время, оптимизирую.
Здравствуйте, Eugene Novikov, Вы писали: EN>Вся проблема в сроках. Если бы была куча времени, я бы спокойно свой парсер написал. А щас мне уже не очень важно на сколько "тяжелее" станет прога из-за сторонних библиотек, главное это скорость реализации нужного функционала. Будет время, оптимизирую.
Вы уже на форум и поиски потратили больше времени. Написать хватит минут 15 (хорошо, час, если делаете это впервые).
Здравствуйте, gegMOPO4, Вы писали:
MOP>Здравствуйте, Eugene Novikov, Вы писали: EN>>Вся проблема в сроках. Если бы была куча времени, я бы спокойно свой парсер написал. А щас мне уже не очень важно на сколько "тяжелее" станет прога из-за сторонних библиотек, главное это скорость реализации нужного функционала. Будет время, оптимизирую.
MOP>Вы уже на форум и поиски потратили больше времени. Написать хватит минут 15 (хорошо, час, если делаете это впервые).
Ну я когда вопрос задавал не сидел тоже и продумывал разные варианты. Для меня важным фактором помимо скорости была гарантированность. Чтобы потом сюрпризов не было. На данный момент все реализовано. Спасибо всем за помощь.