J'ai besoin de rechercher une chaîne et de remplacer toutes les occurrences de %FirstName%
et %PolicyAmount%
par une valeur extraite d'une base de données. Le problème est que la capitalisation de FirstName varie. Cela m'empêche d'utiliser la String.Replace()
méthode. J'ai vu des pages Web sur le sujet qui suggèrent
Regex.Replace(strInput, strToken, strReplaceWith, RegexOptions.IgnoreCase);
Cependant, pour une raison quelconque, lorsque j'essaie de remplacer %PolicyAmount%
par $0
, le remplacement n'a jamais lieu. Je suppose que cela a quelque chose à voir avec le signe dollar étant un caractère réservé dans l'expression régulière.
Y a-t-il une autre méthode que je peux utiliser qui n'implique pas de nettoyer l'entrée pour gérer les caractères spéciaux regex?
Réponses:
À partir de MSDN
$ 0 - "Remplace la dernière sous-chaîne correspondant au numéro de groupe (décimal)."
Dans .NET, le groupe d'expressions régulières 0 correspond toujours à l'intégralité de la correspondance. Pour un $ littéral, vous devez
la source
On dirait que
string.Replace
devrait avoir une surcharge qui prend unStringComparison
argument. Comme ce n'est pas le cas, vous pouvez essayer quelque chose comme ceci:la source
ReplaceString
pourReplace
.oldValue == newValue == ""
.ReplaceString("œ", "oe", "", StringComparison.InvariantCulture)
jetteArgumentOutOfRangeException
.Une sorte de groupe de réponses déroutant, en partie parce que le titre de la question est en réalité beaucoup plus large que la question spécifique posée. Après avoir lu, je ne suis pas sûr qu'une réponse soit à quelques modifications de l'assimilation de toutes les bonnes choses ici, alors j'ai pensé que j'essaierais de résumer.
Voici une méthode d'extension qui, je pense, évite les pièges mentionnés ici et fournit la solution la plus largement applicable.
Alors...
"œ".ReplaceCaseInsensitiveFind("oe", "")
bien qu'il peut avoir eu un comportement légèrement différent à l' esprit.Malheureusement, le commentaire de @HA que vous devez faire aux
Escape
trois n'est pas correct . La valeur initiale etnewValue
n'a pas besoin d'être.Remarque: Cependant, vous devez échapper les
$
s dans la nouvelle valeur que vous insérez s'ils font partie de ce qui semble être un marqueur de "valeur capturée" . Ainsi, les trois signes du dollar dans le Regex.Replace à l'intérieur du Regex.Replace [sic]. Sans cela, quelque chose comme ça se casse ..."This is HIS fork, hIs spoon, hissssssss knife.".ReplaceCaseInsensitiveFind("his", @"he$0r")
Voici l'erreur:
Dites-vous quoi, je sais que les gens qui sont à l'aise avec Regex ont l'impression que leur utilisation évite les erreurs, mais je reste souvent partial pour les chaînes de reniflement d'octets (mais seulement après avoir lu Spolsky sur les encodages ) pour être absolument sûr que vous obtenez ce que vous destiné aux cas d'utilisation importants. Ça me rappelle un peu Crockford sur les " expressions régulières peu sûres ". Trop souvent, nous écrivons des expressions rationnelles qui permettent ce que nous voulons (si nous avons de la chance), mais en autorisons involontairement plus (par exemple, est-ce
$10
vraiment une chaîne de "valeur de capture" valide dans mon expression rationnelle newValue, ci-dessus?) Parce que nous n'étions pas assez réfléchis . Les deux méthodes ont de la valeur et encouragent toutes deux différents types d'erreurs involontaires. Il est souvent facile de sous-estimer la complexité.Cette
$
fuite étrange (et quiRegex.Escape
n'a pas échappé aux modèles de valeur capturés$0
comme je m'y attendais dans les valeurs de remplacement) m'a rendu fou pendant un certain temps. La programmation est difficile (c) 1842la source
Voici une méthode d'extension. Je ne sais pas où je l'ai trouvé.
la source
Il semble que la méthode la plus simple consiste simplement à utiliser la méthode Replace livrée avec .Net et utilisée depuis .Net 1.0:
Pour utiliser cette méthode, vous devez ajouter une référence à l'assembly Microsoft.VisualBasic. Cet assemblage est une partie standard du runtime .Net, ce n'est pas un téléchargement supplémentaire ou marqué comme obsolète.
la source
C. Dragon 76
fonctionné comme prévu.la source
Inspiré par la réponse de cfeduke, j'ai créé cette fonction qui utilise IndexOf pour trouver l'ancienne valeur dans la chaîne, puis la remplace par la nouvelle valeur. Je l'ai utilisé dans un script SSIS traitant des millions de lignes, et la méthode regex était beaucoup plus lente que cela.
la source
Développant la réponse populaire de C. Dragon 76 en faisant de son code une extension qui surcharge la
Replace
méthode par défaut .la source
Basé sur la réponse de Jeff Reddy, avec quelques optimisations et validations:
la source
une version similaire à C. Dragon's, mais si vous n'avez besoin que d'un seul remplacement:
la source
Voici une autre option pour exécuter les remplacements Regex, car peu de gens semblent remarquer que les correspondances contiennent l'emplacement dans la chaîne:
la source
la source
La méthode d'expression régulière devrait fonctionner. Cependant, ce que vous pouvez également faire est de mettre en minuscule la chaîne de la base de données, de mettre en minuscule les% variables% que vous avez, puis de localiser les positions et les longueurs dans la chaîne en minuscules de la base de données. N'oubliez pas que les positions dans une chaîne ne changent pas simplement parce qu'elle est en bas de casse.
Ensuite, en utilisant une boucle qui va dans le sens inverse (c'est plus facile, si vous ne le faites pas, vous devrez garder un compte courant de l'endroit où les points ultérieurs se déplacent) supprimez de votre chaîne non inférieure de la base de données les% variables% par leur position et longueur et insérez les valeurs de remplacement.
la source
(Puisque tout le monde prend une photo à ce sujet). Voici ma version (avec des contrôles nuls, et une entrée correcte et un échappement de remplacement) ** Inspiré d'Internet et d'autres versions:
Usage:
la source
Laissez-moi faire mon cas et vous pourrez me déchirer si vous le souhaitez.
Regex n'est pas la réponse à ce problème - trop lent et gourmand en mémoire, relativement parlant.
StringBuilder est bien meilleur que la manipulation de chaînes.
Étant donné que ce sera une méthode d'extension à compléter
string.Replace
, je pense qu'il est important de faire correspondre comment cela fonctionne - il est donc important de lever des exceptions pour les mêmes problèmes d'argument, tout comme le retour de la chaîne d'origine si aucun remplacement n'a été effectué.Je pense qu'avoir un paramètre StringComparison n'est pas une bonne idée. Je l'ai essayé mais le cas de test mentionné à l'origine par michael-liu a montré un problème: -
Bien qu'IndexOf corresponde, il existe un décalage entre la longueur de la correspondance dans la chaîne source (1) et oldValue.Length (2). Cela s'est manifesté en provoquant IndexOutOfRange dans certaines autres solutions lorsque oldValue.Length a été ajouté à la position de correspondance actuelle et je n'ai pas pu trouver un moyen de contourner cela. Regex ne parvient pas à faire correspondre le cas de toute façon, j'ai donc pris la solution pragmatique de n'utiliser que
StringComparison.OrdinalIgnoreCase
pour ma solution.Mon code est similaire à d'autres réponses mais mon torsion est que je cherche une correspondance avant de me donner la peine de créer un
StringBuilder
. Si aucun n'est trouvé, une allocation potentiellement importante est évitée. Le code devient alors undo{...}while
plutôt qu'unwhile{...}
J'ai fait des tests approfondis contre d'autres réponses et cela est sorti beaucoup plus rapidement et j'ai utilisé un peu moins de mémoire.
la source