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?


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: %%.


14

Untuk melengkapi solusi yang dinyatakan sebelumnya, gunakan:

str = str.replace("%", "%%");

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)", "%%");

-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.)


8
"Aku tidak percaya bahwa ini bukan masalah yang mudah diselesaikan sekarang" << Anda menjawab 6 tahun setelah solusi sederhana diterima.
— AjahnCharles
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.