tags:

views:

63

answers:

6

I have a pipe delimited string like this:

blah|blah|blah|blah|blah|blah|blah|blah|blah|oldDate|blah|blah|

I would like replace the content of the 10th section with a new Date. I am able to match the the old date with the the following code:

'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

However, I can't figure out how to repace that group with new text. I have tried:

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

But that returns the original message like it was unable to find the 4th group. I am unable to do a string replace with the matched date since there are multiple dates in the string (orderDate, receivedDate, etc) and its possible to match on one of those by accident.

Does anyone know how to replace this text?

Thanks in advance for any help.

+3  A: 

There's no apparent reason to use a regex here, use 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);

If you do need to use a regex, consider using Regex.Replace(string, string):

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

Replace works the other way around - you use groups to keep tokens in your string, not to move them out.

Kobi
Exactly, use .split("¦"c), set the array item with index 3 to your new value, and do String.Join("¦", thatArray)
Joachim VR
I like this but I doubt it will work for VB.NET in the way you have presented it.
Michael Eakins
String math and looping is inherently slow.
Brad
Wow, two downvotes! @Brad - Did you profile it? If the OP needs more than a single replace, this is the best method. Besides, there are more important things the a few cycles. As for VB, it is almost the same. It has array, it has String.split, and Join. Nothing special here.
Kobi
The most important thing would be to use the correct language, at least in my opinion that would be important.
Michael Eakins
Kobi, I am currently using split, however this is only one line of would could be as many as 50 and the one line could have as many as 40 pipes. So I have to split first on CR/LF, then on the first line split again on |. Then rebuild the total string. We are seeing some speed issues and someone suggested we try to regex.replace the value in place so we would haven't the rebuild time hit.
dsrekab
+1  A: 

you could use a split

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" 

then

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

or

for each obj1 as object in obj
   str&= obj1
next
Michael Eakins
String math and looping is inherently slow.
Brad
I doubt it would be slow over 10 entries as I've done this over thousands.
Michael Eakins
@Brad - What tool did you use to profile the code?
Kobi
A: 

The Replace method is static. This means that it's not considering the fact that you called it on theRegEx object pipeRegEx and instead looking for the literal string "$4".

I would rewrite my expression using a zero-width look-behind (?<=expression) and zero-width look-ahead (?=expression) so that it only matched the 9th item (and leave it as a string instead of a RegEx). Then you would call:

RegEx.Replace(strMessage,pipeRegEx, newDate);

RegEx syntax resource: http://www.regular-expressions.info/reference.html

Brad
"static" is CSharp-speak. As msarchet pointed out, "Shared" is the VB-speak version of that.
Brad
Static is actually a VB.NET term also but refers to a variable retaining it's value even after the sub or function has been disposed.
Michael Eakins
Try this expression: (?<=([^\|]+\|){9})[^\|]+(?=(\|[^\|]+)+\|*)
Brad
+2  A: 

So what you are doing is this, you are calling a Shared version of the RegEx library on your regex, you aren't actually using your regex to find the match, it is using the "$4" to find a match, which it isn't. This is why you are getting your original string back.

I would do something like this to get the appropriate group replaced with the new date

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

matchedGroups(9) = "new Date"

And then just put your list back together.

msarchet
+2  A: 

You're going about it backward. What you want to do is capture everything preceding the tenth field and then plug it back in along with the new value. You regex looks good, so you just have to change the replacement parameter. Something like this:

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

(You have to plug the | back in as well, because the regex consumes it.)

Alan Moore
A: 

Ok, I was able to get the solution with the help of Brad's answer and a different way to get the solution with Kobi's answer, however I felt Brad's was more succinct.

'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 & "|").
dsrekab
Unless you need the oldDate for something else, you should be able to just call RegEx.Replace(strMessage,"(?<=^(([^\|]*\|){9}))([^\|]*)(?=\|)",newDate)
Brad