2012-11-26 12 views
7

私は外部印刷機能に送る文字列を持っています。
文字列をバックスラッシュで埋めて、正しく印刷する必要があります。この文字列を正しくエスケープする方法

は具体的に、私は、この例の入力を受け入れる方法が必要になります。
This is a string\nwith a line break\ta tab\rand a carriage return.

と出力:
This is a string\\nwith a line break\\ta tab\\rand a carriage return.

は私が力Replaceそれにあらゆる可能なエスケープ文字は、バックスラッシュだと同等のブルートする必要がありますか?

が試した:それは文字通りのバックスラッシュを探しているので s.Replace("\\","\\\\")
は動作しません。

s.Replace("\n","\\n")明らかに機能しますが、私が探しているのは一般的な方法です。

編集: brute forceメソッドを提案しないでください。このようなメソッドを実装するには問題はありません。私の質問はもっと普遍的なアプローチがある場合でした。

+0

あなたの入力は明確ではありません - 「改行を含む文字列」を「バックスラッシュの後にnを付ける文字列」に変換することを意味しますか? –

+0

@ジョンはい、まさに。私はダブルエスケープのために私の文字列を準備する必要があります。 – Rotem

+0

@Rotem @ "これは文字列\ nと改行"ですか?素晴らしい日を過ごしてください:) –

答えて

11
private static string EscapeLiterals(string input) 
{ 
    using (var writer = new StringWriter()) 
    { 
     using (var provider = CodeDomProvider.CreateProvider("CSharp")) 
     { 
      provider.GenerateCodeFromExpression(new CodePrimitiveExpression(input), writer, null); 
      return writer.ToString(); 
     } 
    } 
} 

入力"\tHello\r\n\tLiterals!"を受け取り、任意の入力のための"\\tHello\\r\\n\\tLiterals!"

作品にそれを回す - それはあなたが何のためのエスケープシーケンスを取得します。

+1

ブラボー、ありがとう!クラスが 'System.CodeDom'と' System.CodeDom.Compiler'名前空間に存在することも言及する価値があります。 – Rotem

+0

いいですが、長い文字列の場合、これは "+"演算子、改行とインデントを挿入することに注意してください。私はそれをオフにする方法を見つけることができませんでした。 – Timwi

0

あなたはそれが読める制御文字と空白の置き換え強制するために、複数の置き換えを使用することができます。

s = s.Replace("\n", "\\n").Replace("\r", "\\r").Replace("\t", "\\t"); 

文字がすでにしてメモリに変換されますので、あなたはあなたが思うほど簡単なバックスラッシュを倍にすることはできませんしかし、そのバイナリ値。だから、あなたは手ですべてのチャーを交換する必要があります。

+1

私はこれが機能し、すべての制御文字を処理するメソッドを探していることを知っていると具体的に述べました。 – Rotem

+0

さらにいくつかのルールを追加することもできます... – rekire

+0

例をもっと明確にした場合は、更新しました。 – Rotem

4

ここに私がこれに使用する機能があります。私はこれを数年間プロダクションコードに使用しており、あらゆる種類のコーナーケースに対抗しているようです。

/// <summary> 
/// Escapes all characters in this string whose code is less than 32 using C/C#-compatible backslash escapes. 
/// </summary> 
public static string CLiteralEscape(this string value) 
{ 
    if (value == null) 
     throw new ArgumentNullException("value"); 

    var result = new StringBuilder(value.Length + value.Length/2); 

    for (int i = 0; i < value.Length; i++) 
    { 
     char c = value[i]; 
     switch (c) 
     { 
      case '\0': result.Append(@"\0"); break; 
      case '\a': result.Append(@"\a"); break; 
      case '\b': result.Append(@"\b"); break; 
      case '\t': result.Append(@"\t"); break; 
      case '\n': result.Append(@"\n"); break; 
      case '\v': result.Append(@"\v"); break; 
      case '\f': result.Append(@"\f"); break; 
      case '\r': result.Append(@"\r"); break; 
      case '\\': result.Append(@"\\"); break; 
      case '"': result.Append(@"\"""); break; 
      default: 
       if (c >= ' ') 
        result.Append(c); 
       else // the character is in the 0..31 range 
        result.AppendFormat(@"\x{0:X2}", (int) c); 
       break; 
     } 
    } 

    return result.ToString(); 
} 
+0

これは私が彼のブルートフォースのアプローチを質問で言及したものです - 決してリストアップユニットのテストケースのためにupvoted:P – Markus