2011-10-06 2 views
2

J'ai besoin d'échapper à ces caractères: +-&|!(){}[]^"~*?:\ en les précédant avec un \\. Quelle est la meilleure façon de le faire. Ma première pensée utilisait remplacer, mais cela chercherait la chaîne pour chaque élément à remplacer. Je pense qu'il doit y avoir un moyen de le faire avec des expressions régulières qui obtiendraient tout en un passage.manière optimale d'échapper caractère

+0

Voir cette question: http://stackoverflow.com/questions/323640/can-i-convert-ac-string-value-to-an-escaped-string- littéral –

Répondre

6

Il est possible avec une expression régulière. La partie la plus délicate est correctement les caractères échappe spéciaux sans entrer dans l'enfer backslash:

s = Regex.Replace(s, @"[+\-&|!(){}[\]^""~*?:\\]", "\\$0"); 

La solution StringBuildermentioned by Eric J. est simple et très élégant. Voici une façon de coder:

StringBuilder sb = new StringBuilder(); 
foreach (char c in s) 
{ 
    if ("+-&|!(){}[]^\"~*?:\\".Contains(c)) 
    { 
     sb.Append('\\'); 
    } 
    sb.Append(c); 
} 
s = sb.ToString(); 
+0

+1 pour la solution stringbuilder – Jamiec

+0

Si la chaîne est très grande, utilisez le constructeur StringBuilder qui vous permet de fournir une taille initiale et de la définir légèrement plus grande que la chaîne d'origine. –

0

La meilleure façon de le faire en utilisant sûrement des expressions régulières (Regex)!

string str = @"+-&|!(){}[]^""~*?:\"; 
string pattern = @"(\+|\-|\&|\||\!|\(|\)|\{|\}|\[|\]|\^|\""|\~|\*|\?|\:|\\)"; 
string output = Regex.Replace(str, pattern, @"\$1"); 

donne la sortie suivante:

\+\-\&\|\!\(\)\{\}\[\]\^\"\~\*\?\:\\ 
+1

Pourquoi? RegEx sont pratiques mais peuvent être assez lents. En fait, l'une des rares améliorations présentées dans .NET 4.5 est de limiter le temps d'exécution des expressions régulières. http://en.wikipedia.org/wiki/.NET_Framework_version_history#Common_Language_Runtime_.28CLR.29 –

4

L'utilisation d'un StringBuilder serait probablement une meilleure option que regex. Voici un poste msdn pour soutenir l'idée: Regex.Replace vs String.Replace vs StringBuilder.Replace

public const string CharsToBeEscaped = "+-&|!(){}[]^\"~*?:\\'"; 

string s = "+-&|!(){}[]^\"~*?:\\"; 

StringBuilder sb = new StringBuilder(); 
sb.Append(s); 

for (int i = 0; i < CharsToBeEscaped.Length; i++) { 
    sb.Replace(CharsToBeEscaped.Substring(i,1), @"\" + CharsToBeEscaped[i]); 
} 
sb.Replace(@"\\", @"\"); 

s = sb.ToString(); 
+0

+ ½ pour suggérer StringBuilder. Cependant, après avoir regardé votre article, je pense qu'il démontre une approche légèrement différente que le code dans ma réponse. Je pense que ce n'est pas aussi efficace, mais pas sûr. Aussi je pense que l'article est difficile à lire. Pourriez-vous poster le code que vous utiliseriez? Quoi qu'il en soit, j'ai voté une de vos réponses pour une autre question à la place. :) –

+0

@MarkByers Voici ma mise en œuvre. –

+0

+1 pour fournir le code. Je suis toujours un peu préoccupé par la performance par rapport à mon code ... Je ne l'ai pas testé, mais je pense que c'est plus lent en raison des remplacements répétés. Et il y a aussi un bogue parce qu'il échappe d'abord aux caractères spéciaux avec des barres obliques inverses et ensuite s'échappe * ces * antislashs avec une autre barre oblique inverse, ce que je ne pense pas être ce qu'il veut. –

0

DISCLAIMER: LISEZle arguments dans d'autres réponses sur pas en utilisant regex si cela causera un problème de performance pour votre application (par exemple, si cela est une très grande chaîne avec beaucoup d'instances de vos caractères d'échappement). Cependant, si regex est votre choix, le dessous vous expliquera comment le faire en 1 ligne de code.

C'est Regex.Replace que vous recherchez. Vous fournissez une expression régulière que vous recherchez, l'entrée et un MatchEvaluator qui s'exécute pour chaque match. Dans votre cas, vous venez de retourner String.Concat(@"\",match.Value).

Quelque chose comme ça (input est votre chaîne):

var replaced = Regex.Replace(input, //your string 
     @"[\+\-&|!]", // partial regex to give you an idea 
     match => String.Concat(@"\",match.Value)); //MatchEvaluator, runs for each capture 
1

Les chaînes sont immuables en C#, ce qui signifie que tous les String.replace() va créer une nouvelle copie modifiée de la chaîne d'origine.

Pour de nombreuses applications, cela n'a aucune importance. Puisque vous demandez à ce sujet, cependant, je suppose que cela peut être dans votre cas.

L'approche la plus efficace est probablement d'utiliser un StringBuilder pour construire votre chaîne modifiée. Parcourez une fois la chaîne source et ajoutez le caractère à chaque position de chaîne, ou une version échappée, selon le cas. Utilisez le StringBuilder constructor qui pré-alloue la taille du tampon interne initial pour être légèrement plus grande que la chaîne source. RegEx, auquel la plupart des autres réponses font allusion, sera probablement aussi très efficace pour cette application particulière et impliquera moins de code. Cependant, puisque RegEx doit intrinsèquement appliquer une logique d'analyse généralisée, elle ne peut pas être aussi rapide qu'une solution adaptée à vos besoins spécifiques. En outre, dans certains cas (probablement pas celui-ci si), RegEx peut être très lent.Voir

http://en.wikipedia.org/wiki/.NET_Framework_version_history#Common_Language_Runtime_.28CLR.29

http://www.codinghorror.com/blog/2006/01/regex-performance.html

+0

Petite puce. Votre description de la capacité de StringBuilder n'est pas très précise. Dans .NET 3.5 et plus tôt la capacité était toujours 2^n. Il était donc exactement égal à la chaîne source et presque deux fois plus grand que la chaîne source. Dans 4.0, la capacité est la même que la chaîne source. (Pour les deux la capacité min = 16). –

Questions connexes