Bagaimana cara menghindari% di String.Format?

445

Saya menyimpan query SQL dalam file strings.xml saya dan saya ingin menggunakan String.Formatuntuk membangun string terakhir dalam kode. The SELECTpernyataan menggunakan seperti, sesuatu seperti ini:

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

Untuk memformat yang saya ganti 'sesuatu' dengan% 1 $ s sehingga menjadi:

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

Saya lolos dari tanda kutip tunggal dengan garis miring terbalik. Namun saya tidak dapat lepas dari tanda%.

Bagaimana saya bisa memasukkan pernyataan suka dalam file strings.xml saya?

Matius
sumber
Jangan lupa untuk keluar dari% s dengan benar.
Seva Alekseyev
Mereka akan menyuntikkan ke dalam database mereka sendiri, tidak ada masalah di sini;)
Matius
7
Yah, bahkan jika itu adalah database Anda sendiri, adalah mungkin untuk secara tidak sengaja menulis pertanyaan yang melakukan hal-hal buruk. Atau cukup tulis pertanyaan yang tidak dikompilasi. Mempersiapkan pertanyaan adalah kebiasaan yang baik untuk dilakukan.
Rauni Lillemets
Meskipun lebih lambat dari String.format()yang mungkin Anda pertimbangkan untuk menggunakannya MessageFormat().
ccpizza

Jawaban:

926

Untuk melarikan diri %, Anda akan perlu dua itu: %%.

limc
sumber
14

Untuk melengkapi solusi yang dinyatakan sebelumnya, gunakan:

str = str.replace("%", "%%");
Cavaleiro
sumber
1
Ini akan menggantikan% yang sudah dua kali lipat. Silakan baca jawaban lainnya.
Toilal
1
@Toalal Mengapa ada orang yang lolos dari sesuatu yang sudah lolos? Dan jika dia mau, mengapa tidak benar-benar melakukannya? Mungkin dia bermaksud memiliki dua tanda%, jadi bentuk yang benar yang lolos adalah '%%%%'
David Balažic
2

Ini adalah pengganti regex yang lebih kuat yang tidak akan menggantikan %% yang sudah dua kali lipat dalam input.

str = str.replaceAll("(?:[^%]|\\A)%(?:[^%]|\\z)", "%%");
Kerja keras
sumber
-3

Berikut adalah opsi jika Anda perlu melarikan diri beberapa% dalam sebuah string dengan beberapa sudah lolos.

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

Untuk membersihkan pesan sebelum meneruskannya ke String.format, Anda dapat menggunakan yang berikut ini

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

Ini berfungsi dengan sejumlah karakter pemformatan, sehingga akan menggantikan% dengan %%, %%% dengan %%%%, %%%%% dengan %%%%%%, dll.

Ini akan membiarkan karakter yang sudah lolos saja (mis. %%, %%%%, dll.)

Lee Winder
sumber
8
"Aku tidak percaya bahwa ini bukan masalah yang mudah diselesaikan sekarang" << Anda menjawab 6 tahun setelah solusi sederhana diterima.
AjahnCharles