Jak uciec% w String.Format?

445

Przechowuję zapytanie SQL w moim pliku strings.xml i chcę użyć go String.Formatdo zbudowania ostatniego ciągu w kodzie. W SELECToświadczeniu używa się czegoś podobnego:

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

Aby sformatować, zamieniam „coś” na% 1 $ s, aby stało się:

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

Unikam pojedynczych cudzysłowów odwrotnym ukośnikiem. Nie jestem jednak w stanie uciec od znaku%.

Jak mogę dołączyć podobną instrukcję do mojego pliku strings.xml?

Mateusz
źródło
Nie zapomnij odpowiednio uciec z% s.
Seva Alekseyev
Będą wstrzykiwać do własnej bazy danych, bez względu na to;)
Matthew
7
Cóż, nawet jeśli jest to Twoja własna baza danych, możliwe jest przypadkowe pisanie zapytań, które robią złe rzeczy. Lub po prostu napisz zapytania, które się nie kompilują. Przygotowanie zapytań jest dobrym nawykiem.
Rauni Lillemets
Chociaż jest wolniejszy, niż String.format()możesz rozważyć użycie MessageFormat()zamiast niego.
ccpizza

Odpowiedzi:

926

Uciec %, trzeba będzie podwoić go: %%.

limc
źródło
14

Aby uzupełnić poprzednie podane rozwiązanie, użyj:

str = str.replace("%", "%%");
Cavaleiro
źródło
1
Spowoduje to zastąpienie%, które są już podwojone. Przeczytaj drugą odpowiedź.
Toilal 27.07.16
1
@Toilal Dlaczego ktokolwiek miałby uciekać przed czymś, co już uciekło? A jeśli by tak zrobił, dlaczego właściwie tego nie zrobić? Może zamierzał mieć dwa znaki%, więc poprawną formą zmiany znaczenia będzie „%%%%”
David Balažic
2

Jest to silniejsze zastępowanie wyrażeń regularnych, które nie zastąpi %%, które są już podwojone w danych wejściowych.

str = str.replaceAll("(?:[^%]|\\A)%(?:[^%]|\\z)", "%%");
Toilal
źródło
-3

Oto opcja, jeśli musisz uciec wielu% w ciągu, a niektóre już uciekły.

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

Aby zdezynfekować wiadomość przed przekazaniem jej do String.format, możesz użyć następujących

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();

Działa to z dowolną liczbą znaków formatujących, więc zastąpi%%%, %%% z %%%%, %%%%% z %%%%%% itp.

Pozostawi już wszelkie znaki, które uciekły w spokoju (np. %%, %%%% itp.)

Lee Winder
źródło
8
„Nie mogę uwierzyć, że nie jest to do tej pory prosty rozwiązany problem” << Odpowiedziałeś 6 lat po przyjęciu prostego rozwiązania.
AjahnCharles