Как избежать% в String.Format?

446

Я храню запрос SQL в моем файле strings.xml, и я хочу использовать String.Formatдля создания окончательной строки в коде. В SELECTзаявлении используется что-то вроде этого:

SELECT Field1, Field2 FROM mytable WHERE Field1 LIKE '%something%'

Чтобы отформатировать это, я заменяю 'что-то' на% 1 $ s, таким образом это становится:

SELECT Field1, Field2 FROM mytable WHERE Field1 LIKE \'%%1$s%\'

Я избегаю одинарных кавычек с обратной косой чертой. Однако я не могу избежать знака%.

Как я могу включить оператор like в мой файл strings.xml?

Мэтью
источник
Не забудьте правильно избежать% s.
Сева Алексеев
Они будут делать инъекции в свою собственную базу данных, не беспокойтесь здесь;)
Мэтью
7
Ну, даже если это ваша собственная база данных, можно случайно написать запросы, которые делают плохие вещи. Или просто пишите запросы, которые не компилируются. Подготовка запросов - хорошая привычка.
Рауни Лиллемец
Хотя это медленнее, чем String.format()вы могли бы использовать MessageFormat()вместо этого.
ccpizza

Ответы:

928

Для того, чтобы избежать %, вам нужно будет удвоить его: %%.

LIMC
источник
14

Чтобы дополнить предыдущее решение, используйте:

str = str.replace("%", "%%");
Cavaleiro
источник
1
Это заменит%, который уже удвоен. Пожалуйста, прочитайте другой ответ.
Toilal
1
@Toilal Зачем кому-то избегать того, что уже сбежало? И если он хочет, то почему бы на самом деле не сделать это? Возможно, он собирался иметь два знака%, поэтому правильной экранированной формой будет «%%%%»
Дэвид Балажич,
2

Это более сильная замена регулярных выражений, которая не заменит %%, который уже удвоен во входных данных.

str = str.replaceAll("(?:[^%]|\\A)%(?:[^%]|\\z)", "%%");
Toilal
источник
-3

Вот вариант, если вам нужно экранировать несколько% в строке, а некоторые уже экранированы.

(?:[^%]|^)(?:(%%)+|)(%)(?:[^%])

Чтобы очистить сообщение перед его передачей в String.format, вы можете использовать следующее

Pattern p = Pattern.compile("(?:[^%]|^)(?:(%%)+|)(%)(?:[^%])");
Matcher m1 = p.matcher(log);

StringBuffer buf = new StringBuffer();
while (m1.find())
    m1.appendReplacement(buf, log.substring(m1.start(), m1.start(2)) + "%%" + log.substring(m1.end(2), m1.end()));

// Return the sanitised message
String escapedString = m1.appendTail(buf).toString();

Это работает с любым количеством символов форматирования, поэтому он заменит% на %%, %%% на %%%%, %%%%% на %%%%%% и т. Д.

Любые уже экранированные символы останутся без изменений (например, %%, %%%% и т. Д.)

Ли Виндер
источник
8
«Я не могу поверить, что это не простая решаемая проблема» << Вы ответили через 6 лет после того, как было принято простое решение.
AjahnCharles