2010-09-16 10 views
4

J'ai une chaîne délimitée par un tuyau comme ceci:Comment remplacer le nième groupe regex par une nouvelle chaîne dans .net?

blah | bla | bla | bla | bla | bla | bla | bla | bla | ancienDate | bla | bla |

Je voudrais remplacer le contenu de la 10e section par une nouvelle date. Je suis en mesure de correspondre à la l'ancienne date avec le code suivant:

'create a group with the first 9 non-pipes followed by a pipe, a group with the old date followed by a pipe, and sub-group of just the old date. 
Dim pipeRegEx As New RegularExpressions.Regex("(([^\|]*\|){9})(([^\|]*)\|)") 

'the sub-group is the 4th group ordinal in the match GroupCollection 
Dim oldDate as String=pipeRegEx.Match(strMessage).Groups(4).Value 

Cependant, je ne peux pas comprendre comment Repace ce groupe avec le nouveau texte. J'ai essayé:

pipeRegEx.Replace(strMessage, "$4", newDate) 'where newDate is a string var 

Mais cela renvoie le message original comme s'il était incapable de trouver le 4ème groupe. Je ne peux pas remplacer une chaîne par la date correspondante car il y a plusieurs dates dans la chaîne (orderDate, receivedDate, etc.) et il est possible de faire correspondre une de ces chaînes par accident.

Est-ce que quelqu'un sait comment remplacer ce texte?

Merci d'avance pour toute aide.

Répondre

0

Le Replace method est static. Cela signifie qu'il ne tient pas compte du fait que vous l'avez appelé sur l'objetRegEx pipeRegEx et que vous recherchez plutôt la chaîne littérale "$ 4".

Je réécrire mon expression à l'aide d'un zéro largeur regarder en arrière (?<=expression) et zéro largeur look-ahead (?=expression) afin qu'il ne correspond le 9 article (et le laisser comme une chaîne au lieu d'un RegEx). Ensuite, vous appelez:

RegEx.Replace(strMessage,pipeRegEx, newDate); 

RegEx ressource de syntaxe: http://www.regular-expressions.info/reference.html

+0

"statique" est CSharp-parler. Comme msarchet l'a souligné, "Shared" est la version VB-speak de cela. – Brad

+0

Static est en fait un terme VB.NET mais fait référence à une variable conservant sa valeur même après que le sous-marin ou la fonction a été éliminée. –

+0

Essayez cette expression: (? <= ([^ \ |] + \ |) {9}) [^ \ |] + (? = (\ | [^ \ |] +) + \ | *) – Brad

3

Il n'y a pas de raison apparente d'utiliser une regex ici, utilisez strMessage.Split('|').

string str = "blah|blah|blah|blah|blah|blah|blah|blah|blah|oldDate|blah|blah"; 
string[] tokens = str.Split('|'); 
tokens[9] = "newDate"; 
string newStr = String.Join("|", tokens); 

Si vous avez besoin d'utiliser une expression régulière, pensez à utiliser Regex.Replace(string, string):

pipeRegEx.Replace(strMessage, "$2" & newDate & "|") 

Remplacer fonctionne dans l'autre sens - vous utilisez des groupes pour garder des jetons dans votre chaîne, de ne pas les déplacer en dehors.

+0

Exactement, utilisez .split ("|" c), définissez l'élément tableau avec un indice 3 à votre nouvelle valeur et faire String.Join ("|", thatArray) –

+0

J'aime cela, mais je doute fonctionnera pour VB.NET de la façon dont vous l'avez présenté. –

+0

Les mathématiques et les boucles sont intrinsèquement lentes. – Brad

1

vous pouvez utiliser une scission

Dim str As String = "blah|blah|blah|blah|blah|blah|blah|blah|blah|oldDate|blah|blah|" 
Dim obj As Object = str.Split("|") 
obj(9) = "new date" 

puis

str = strings.join(obj, "|") 

ou

for each obj1 as object in obj 
    str&= obj1 
next 
+0

Les mathématiques et les boucles sont intrinsèquement lentes. – Brad

+0

Je doute qu'il serait lent sur 10 entrées que j'ai fait cela sur des milliers. –

+1

@Brad - Quel outil avez-vous utilisé pour profiler le code? – Kobi

2

Donc ce que vous faites est, vous appelez une version Shared de la bibliothèque RegEx sur votre regex, vous n'êtes pas En fait, en utilisant votre regex pour trouver le match, il utilise le "$4" pour trouver une correspondance, ce qui n'est pas le cas. C'est pourquoi vous récupérez votre chaîne d'origine.

je ferais quelque chose comme ça pour obtenir le groupe approprié remplacé par la nouvelle date

Dim matchedGroups As New System.Text.RegularExpressions.Matches = pipeRegEx.Matches(strMessage) 

matchedGroups(9) = "new Date" 

Et puis il suffit de mettre votre liste ensemble.

2

Vous partez à l'envers. Qu'est-ce que vous voulez faire est de capturer tout précédant le dixième champ, puis rebranchez-le avec la nouvelle valeur. Vous regex semble bon, il vous suffit de changer le paramètre de remplacement. Quelque chose comme ceci:

newString = pipeRegEx.Replace(strMessage, "$1" + newDate + "|") 

(. Vous devez brancher le | retour en tant que bien, parce que le regex consomme)

0

Ok, j'ai pu obtenir la solution avec l'aide de la réponse de Brad et Une façon différente d'obtenir la solution avec la réponse de Kobi, mais je sentais que Brad était plus succint.

'This regex does a look behind for the string that starts with 9 sections 
'and another look ahead for the next pipe. So the result of this regex is only 
'the old date value. 
Dim pipeRegEx As New RegularExpressions.Regex("(?<=^(([^\|]*\|){9}))([^\|]*)(?=\|)") 

'I then store the old date with: 
oldDate=pipeRegEx.Match(strMessage).Value 

'And replace it with the new date: 
strMessage=pipeRegEx.Replace(strMessage, newDate & "|"). 
+0

Sauf si vous besoin de l'ancienne date pour autre chose, vous devriez pouvoir appeler simplement RegEx.Replace (strMessage, "(? <=^(([^ \ |] * \ |) {9})) ([^ \ |] *) (? = \ |) ", nouveauDate) – Brad

Questions connexes