Reputation: 251
I was wondering is there a way to split a string on the 3rd occurence of a char? When splitting previously i was using:
line.Substring(line.LastIndexOf(']') +1);
I hadn't realised some of my strings had extra square brackets than others so ideally i need to split on the 3rd occurence of ']' as this is the same position on every string.
Input: [Wed Dec 17 14:40:28 2014] [error] [client 143.117.101.166] File does not exist:
Output:
[Wed Dec 17 14:40:28 2014] [error] [client 143.117.101.166]
File does not exist:
Upvotes: 5
Views: 3478
Reputation: 885
Use Regex to solve the problem,this will capture content with []
string input = " [Wed Dec 17 14:40:28 2014] [error] [client 143.117.101.166] File does not exist";
var regex = new Regex("\\[(.*?)\\]");
var matches = regex.Matches(input);
foreach (var match in matches) // e.g. you can loop through your matches like this
{
//yourmatch
}
Upvotes: 2
Reputation: 123
I would do it like this:
public static class SplitExtension
{
public static string[] Split(this string self, char separator, int occurrence)
{
return self.Split(new string(separator, 1), occurrence);
}
public static string[] Split(this string self, string separator, int occurrence)
{
string[] chunks = self.Split(new[] { separator }, StringSplitOptions.None);
string firstPart = string.Join(separator, chunks.Take(occurrence)) + separator;
string secondPart = string.Join(separator, chunks.Skip(occurrence));
return new string[] { firstPart, secondPart };
}
}
... and then use it like this:
string input = "[Wed Dec 17 14:40:28 2014] [error] [client 143.117.101.166] File does not exist";
string[] output = input.Split(']', 3);
// output[0] = "[Wed Dec 17 14:40:28 2014] [error] [client 143.117.101.166]";
// output[1] = " File does not exist";
Upvotes: 0
Reputation: 1996
Another possibility using Linq:
(Take chars from the string until you've seen three square close brackets, then send the output back to the String constructor as an array.)
static void Main(string[] args)
{
string test = "[Wed Dec 17 14:40:28 2014] [error] [client 143.117.101.166] File does not exist:";
var result = SplitOnChar(test, ']', 3);
Debug.WriteLine(result.Item1);
Debug.WriteLine(result.Item2);
}
static Tuple<string, string> SplitOnChar(string input, char c, int occurrence)
{
int charCount = 0;
string firstPart = new String(input.TakeWhile(x => (x == ']' ? charCount++ : charCount) < 3).ToArray());
string lastPart = input.Substring(firstPart.Length);
return Tuple.Create(firstPart, lastPart);
}
Credit goes to this answer for the technique: LINQ, simplifying expression - take while sum of taken does not exceed given value
Upvotes: 0
Reputation: 182
you need to split the string first then take the index of the 3rd ]
line.Substring(line.IndexOf(line.Split(']')[3]));
or more easy as you said the 3rd index of ] is the same, put it fixed
line.Substring(59);
Upvotes: 7
Reputation: 726499
This input can be matched with a regular expression:
\[[^\]]*\]\s*\[[^\]]*\]\s*\[[^\]]*\]
This looks scary because of escape sequences, but the structure is very straightforward: it matches three occurrences of [
+ zero or more non-]
+ ]
, separated by zero or more spaces.
var s = "[Wed Dec 17 14:40:28 2014] [error] [client 143.117.101.166] File does not exist:";
var r = new Regex(@"(\[[^\]]*\]\s*\[[^\]]*\]\s*\[[^\]]*\])(.*)$");
var m = r.Match(s);
if (m.Success) {
Console.WriteLine("Prefix: {0}", m.Groups[1]);
Console.WriteLine("Error: {0}", m.Groups[2]);
}
Upvotes: 5
Reputation: 89
You can use LINQ:
string input = "[Wed Dec 17 14:40:28 2014] [error] [client 143.117.101.166] File does not exist:";
var result = input.Select((ch, ind) => new { ch, ind }).Where(x => x.ch == ']').Skip(2).FirstOrDefault();
string output = input.Substring(result.ind + 1);
Upvotes: 0
Reputation: 4219
If this is a common task you can create an extension method that gives you all the positions where the character you want is, something like:
static class ExtMethods
{
public static IEnumerable<int> IndexesOf(this string str, char c)
{
for (int i = 0; i < str.Length; i++)
{
if (str[i] == c)
yield return i;
}
}
}
Then you can get the position of the third ]
with something like:
int thirdPos = str.IndexesOf(']').Take(3).Last();
Upvotes: 0
Reputation: 80
Okay, as far as I know, C# does not have an inbuilt function for what you seek. Using Regular Expressions is an alternative you could use.
If not, there's another way in which you could get your desired outcome, but that will work only for these particular set of strings. But again, REGEX
too has the same problem.
In your string, if you observe the first two occurrences of ]
are always followed by [
What I am suggesting is, whenever you find the index of ]
you could just check the next character in the string, and if the next character is not [
only then you have to split.
There are infinite number of ways to solve your problem, select the one which makes your code the most modular.
Hope this helps.
Upvotes: 0
Reputation: 31106
I'd go for a simple Split in this case:
var items = line.Split(new[]{']','['},StringSplitOptions.RemoveEmptyEntries);
if (items.Count > 3) {
/* use items[2], or whatever you need... */
}
Because the first items are always bracketted and the same format, this will work.
Upvotes: 0