I experience a strange behaviour when working with RegEx.
dataString = "#Name #Location New York #Rating"
string[] rawValues = Regex.Split(dataString.Trim(), "(^|\\s)+#\\w+");
The pattern matches: "#Name", " #Location", " #Rating" (which is what I intend to match).
The split returns: ["", "", "", " ", "New York", " ", ""]
Question #1: The cunfusion starts already here. Why are there empty strings at positions 0,1,2? Two for the matches and one because it was at the first position of the string?
But this was not the strange part.
string[] rawValues = Regex.Split(dataString.Trim(), "(\\s|^)+#(\\w*[A-Za-z_]+\\w*)");
The pattern matches: "#Name", " #Location", " #Rating" (the same as before).
But the split returns: ["", "", "Name", "", " ", "Location"," New York", " ", "Rating",""]
Question #2: A pattern which leads to the exact same match, results in a totally different split output. How is this possible??
The reason is this sentence from MSDN:
You you shouldn’t use capturing groups in
Splitif you really just want to split the string at matches. You can avoid capturing groups, by using(?:...)in place of every(...)you have.Plus, as you correctly assumed. The first and last
""originate from the fact that the string starts and ends with a match (so the empty string before and after these matches will be reported in the split).Here is a regular expression that is better suited for you purposes:
Note that having the
+outside of your first subpattern was also unnecessary and led to awkward side effects. Firstly it allowed the group to capture multiple times (which is why you got two addition"","": one for^and one for\s). Secondly, there is no need to repeat^after the first space character has been matched, so it is enough to repeat only the space character. Also, there is no need to group the word after#at all.However, if all you want is to match something like
#namewhen it is at the start of the string or preceded by a space (i.e. not* preceded by a **non-space character), why include possible spaces in the match at all. A negative lookbehind gives you a nice way out:This does exactly what described above. The
(?<!\S)matches if there is no non-space character left to it (without including a space-character in the match if there is one). That covers both cases without alternation, and you don’t need toTrimyour key names.