Reputation: 19
how can I retrieve both string between STRING
& END
in this sentence
"This is STRING a222 END, and this is STRING b2838 END."
strings that I want to get:
a222
b2838
Following is my code, and i only manage to get first string which is a222
string myString = "This is STRING a222 END, and this is STRING b2838 END.";
int first = myString.IndexOf("STRING") + "STRING".Length;
int second= myString.LastIndexOf("END");
string result = St.Substring(first, second - first);
.
Upvotes: 0
Views: 162
Reputation: 552
string myString = "This is STRING a222 END, and this is STRING b2838 END.";
// Fix the issue based on @PaulF's comment.
if (myString.StartsWith("STRING"))
myString = $"DUMP {myString}";
var arr = myString.Split(new string[] { "STRING", "END" }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < arr.Length; i++)
{
if(i%2 > 0)
{
// This is your string
Console.WriteLine(arr[i].Trim());
}
}
Upvotes: 0
Reputation: 1369
You've already got some good answers but I'll add another that uses ReadOnlyMemory from .NET core. That provides a solution that doesn't allocate new strings which can be nice. C# iterators are a common way to transform one sequence, of chars in this case, into another. This method would be used to transform the input string into sequence of ReadOnlyMemory each containing the tokens your after.
public static IEnumerable<ReadOnlyMemory<char>> Tokenize(string source, string beginPattern, string endPattern)
{
if (string.IsNullOrEmpty(source) ||
string.IsNullOrEmpty(beginPattern) ||
string.IsNullOrEmpty(endPattern))
yield break;
var sourceText = source.AsMemory();
int start = 0;
while (start < source.Length)
{
start = source.IndexOf(beginPattern, start);
if (-1 != start)
{
int end = source.IndexOf(endPattern, start);
if (-1 != end)
{
start += beginPattern.Length;
yield return sourceText.Slice(start, (end - start));
}
else
break;
start = end + endPattern.Length;
}
else
{
break;
}
}
}
Then you'd just call it like so to iterate over the tokens...
static void Main(string[] args)
{
const string Source = "This is STRING a222 END, and this is STRING b2838 END.";
foreach (var token in Tokenize(Source, "STRING", "END"))
{
Console.WriteLine(token);
}
}
Upvotes: 1
Reputation: 16049
You can iterate over indexes,
string myString = "This is STRING a222 END, and this is STRING b2838 END.";
//Jump to starting index of each `STRING`
for(int i = myString.IndexOf("STRING");i > 0; i = myString.IndexOf("STRING", i+1))
{
//Get Index of each END
var endIndex = myString.Substring(i + "STARTING".Length).IndexOf("END");
//PRINT substring between STRING and END of each occurance
Console.WriteLine(myString.Substring(i + "STARTING".Length-1, endIndex));
}
In your case, STRING..END
occurs multiple times, but you were getting index of only first STRING
and last index of END
which will return substring, starts with first STRING
to last END
.
i.e.
a222 END, and this is STRING b2838
Upvotes: 1
Reputation: 1878
Here is the solution using Regular Expressions. Working Code here
var reg = new Regex("(?<=STRING ).*?(?= END)");
var matched = reg.Matches("This is STRING a222 END, and this is STRING b2838 END.");
foreach(var m in matched)
{
Console.WriteLine(m.ToString());
}
Upvotes: 2
Reputation: 376
You can pass a value for startIndex to string.IndexOf(), you can use this while looping:
IEnumerable<string> Find(string input, string startDelimiter, string endDelimiter)
{
int first = 0, second;
do
{
// Find start delimiter
first = input.IndexOf(startDelimiter, startIndex: first) + startDelimiter.Length;
if (first == -1)
yield break;
// Find end delimiter
second = input.IndexOf(endDelimiter, startIndex: first);
if (second == -1)
yield break;
yield return input.Substring(first, second - first).Trim();
first = second + endDelimiter.Length + 1;
}
while (first < input.Length);
}
Upvotes: 1