String.Formatで%をエスケープする方法は?


445

私は自分のstrings.xmlファイルにSQLクエリを格納しておりString.Format、コードで最終的な文字列を作成するために使用したいと思います。SELECT声明は以下のように、このようなものを使用しています。

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

それをフォーマットするには、「何か」を%1 $ sに置き換えるため、次のようになります。

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

バックスラッシュで一重引用符をエスケープします。ただし、%記号をエスケープすることはできません。

strings.xmlファイルにlikeステートメントを含めるにはどうすればよいですか?


%sを適切にエスケープすることを忘れないでください。
Seva Alekseyev、2011


彼らは彼ら自身のデータベースに注入しているでしょう、ここでは心配ありません;)
マシュー

7
まあ、それがあなた自身のデータベースであったとしても、誤って悪いことをするクエリを書く可能性があります。または、コンパイルしないクエリを記述します。クエリを準備するのは良い習慣です。
Rauni Lillemets 2014年

代わりにString.format()使用を検討するよりも遅いですがMessageFormat()
-ccpizza

回答:


926

エスケープ%するには、2倍にする必要があります%%


14

前述のソリューションを補完するには、次を使用します。

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

1
これにより、すでに2倍になっている%が置き換えられます。他の答えを読んでください。
Toilal

1
@Toilalなぜ誰かがすでに脱出しているものを脱出するのでしょうか?そして、もしそうなら、実際にそれをしないのはなぜですか?多分彼は2つの%記号を付けるつもりだったので、正しいエスケープ形式は '%%%%'になります
DavidBalažicOct

2

これは、入力ですでに2倍になっている%%を置き換えない、より強力な正規表現の置き換えです。

str = str.replaceAll("(?:[^%]|\\A)%(?:[^%]|\\z)", "%%");

-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、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.