I have a string like:
"super example of string key : text I want to keep - end of my string"
I want to just keep the string which is between "key : "
and " - "
. How can I do that? Must I use a Regex or can I do it in another way?
I have a string like:
"super example of string key : text I want to keep - end of my string"
I want to just keep the string which is between "key : "
and " - "
. How can I do that? Must I use a Regex or can I do it in another way?
Perhaps, a good way is just to cut out a substring:
String St = "super exemple of string key : text I want to keep - end of my string";
int pFrom = St.IndexOf("key : ") + "key : ".Length;
int pTo = St.LastIndexOf(" - ");
String result = St.Substring(pFrom, pTo - pFrom);
string input = "super exemple of string key : text I want to keep - end of my string";
var match = Regex.Match(input, @"key : (.+?)-").Groups[1].Value;
or with just string operations
var start = input.IndexOf("key : ") + 6;
var match2 = input.Substring(start, input.IndexOf("-") - start);
You can do it without regex
input.Split(new string[] {"key :"},StringSplitOptions.None)[1]
.Split('-')[0]
.Trim();
Here is the way how i can do that
public string Between(string STR , string FirstString, string LastString)
{
string FinalString;
int Pos1 = STR.IndexOf(FirstString) + FirstString.Length;
int Pos2 = STR.IndexOf(LastString);
FinalString = STR.Substring(Pos1, Pos2 - Pos1);
return FinalString;
}
Depending on how robust/flexible you want your implementation to be, this can actually be a bit tricky. Here's the implementation I use:
public static class StringExtensions {
/// <summary>
/// takes a substring between two anchor strings (or the end of the string if that anchor is null)
/// </summary>
/// <param name="this">a string</param>
/// <param name="from">an optional string to search after</param>
/// <param name="until">an optional string to search before</param>
/// <param name="comparison">an optional comparison for the search</param>
/// <returns>a substring based on the search</returns>
public static string Substring(this string @this, string from = null, string until = null, StringComparison comparison = StringComparison.InvariantCulture)
{
var fromLength = (from ?? string.Empty).Length;
var startIndex = !string.IsNullOrEmpty(from)
? @this.IndexOf(from, comparison) + fromLength
: 0;
if (startIndex < fromLength) { throw new ArgumentException("from: Failed to find an instance of the first anchor"); }
var endIndex = !string.IsNullOrEmpty(until)
? @this.IndexOf(until, startIndex, comparison)
: @this.Length;
if (endIndex < 0) { throw new ArgumentException("until: Failed to find an instance of the last anchor"); }
var subString = @this.Substring(startIndex, endIndex - startIndex);
return subString;
}
}
// usage:
var between = "a - to keep x more stuff".Substring(from: "-", until: "x");
// returns " to keep "
I think this works:
static void Main(string[] args)
{
String text = "One=1,Two=2,ThreeFour=34";
Console.WriteLine(betweenStrings(text, "One=", ",")); // 1
Console.WriteLine(betweenStrings(text, "Two=", ",")); // 2
Console.WriteLine(betweenStrings(text, "ThreeFour=", "")); // 34
Console.ReadKey();
}
public static String betweenStrings(String text, String start, String end)
{
int p1 = text.IndexOf(start) + start.Length;
int p2 = text.IndexOf(end, p1);
if (end == "") return (text.Substring(p1));
else return text.Substring(p1, p2 - p1);
}
A working LINQ solution:
string str = "super example of string key : text I want to keep - end of my string";
string res = new string(str.SkipWhile(c => c != ':')
.Skip(1)
.TakeWhile(c => c != '-')
.ToArray()).Trim();
Console.WriteLine(res); // text I want to keep
Regex is overkill here.
You could use string.Split
with the overload that takes a string[]
for the delimiters but that would also be overkill.
Look at Substring
and IndexOf
- the former to get parts of a string given and index and a length and the second for finding indexed of inner strings/characters.
In C# 8.0 and above, you can use the range operator ..
as in
var s = "header-THE_TARGET_STRING.7z";
var from = s.IndexOf("-") + "-".Length;
var to = s.IndexOf(".7z");
var versionString = s[from..to]; // THE_TARGET_STRING
See documentation for details.
string str="super exemple of string key : text I want to keep - end of my string";
int startIndex = str.IndexOf("key") + "key".Length;
int endIndex = str.IndexOf("-");
string newString = str.Substring(startIndex, endIndex - startIndex);
or, with a regex.
using System.Text.RegularExpressions;
...
var value =
Regex.Match(
"super exemple of string key : text I want to keep - end of my string",
"key : (.*) - ")
.Groups[1].Value;
with a running example.
You can decide if its overkill.
as an under validated extension method
using System.Text.RegularExpressions;
public class Test
{
public static void Main()
{
var value =
"super exemple of string key : text I want to keep - end of my string"
.Between(
"key : ",
" - ");
Console.WriteLine(value);
}
}
public static class Ext
{
static string Between(this string source, string left, string right)
{
return Regex.Match(
source,
string.Format("{0}(.*){1}", left, right))
.Groups[1].Value;
}
}
Since the :
and the -
are unique you could use:
string input;
string output;
input = "super example of string key : text I want to keep - end of my string";
output = input.Split(new char[] { ':', '-' })[1];
I used the code snippet from Vijay Singh Rana which basically does the job. But it causes problems if the firstString
does already contain the lastString
. What I wanted was extracting a access_token from a JSON Response (no JSON Parser loaded). My firstString
was \"access_token\": \"
and my lastString
was \"
. I ended up with a little modification
string Between(string str, string firstString, string lastString)
{
int pos1 = str.IndexOf(firstString) + firstString.Length;
int pos2 = str.Substring(pos1).IndexOf(lastString);
return str.Substring(pos1, pos2);
}
You can use the extension method below:
public static string GetStringBetween(this string token, string first, string second)
{
if (!token.Contains(first)) return "";
var afterFirst = token.Split(new[] { first }, StringSplitOptions.None)[1];
if (!afterFirst.Contains(second)) return "";
var result = afterFirst.Split(new[] { second }, StringSplitOptions.None)[0];
return result;
}
Usage is:
var token = "super exemple of string key : text I want to keep - end of my string";
var keyValue = token.GetStringBetween("key : ", " - ");
var matches = Regex.Matches(input, @"(?<=key :)(.+?)(?=-)");
This returns only the value(s) between "key :" and the following occurance of "-"
If you are looking for a 1 line solution, this is it:
s.Substring(s.IndexOf("eT") + "eT".Length).Split("97".ToCharArray()).First()
The whole 1 line solution, with System.Linq
:
using System;
using System.Linq;
class OneLiner
{
static void Main()
{
string s = "TextHereTisImortant973End"; //Between "eT" and "97"
Console.WriteLine(s.Substring(s.IndexOf("eT") + "eT".Length)
.Split("97".ToCharArray()).First());
}
}
private string gettxtbettwen(string txt, string first, string last)
{
StringBuilder sb = new StringBuilder(txt);
int pos1 = txt.IndexOf(first) + first.Length;
int len = (txt.Length ) - pos1;
string reminder = txt.Substring(pos1, len);
int pos2 = reminder.IndexOf(last) - last.Length +1;
return reminder.Substring(0, pos2);
}
When questions are stated in terms of a single example ambiguities are inevitably present. This question is no exception.
For the example given in the question the desired string is clear:
super example of string key : text I want to keep - end of my string
^^^^^^^^^^^^^^^^^^^
However, this string is but an example of strings and boundary strings for which certain substrings are to be identified. I will consider a generic string with generic boundary strings, represented as follows.
abc FF def PP ghi,PP jkl,FF mno PP pqr FF,stu FF vwx,PP yza
^^^^^^^^^^^^ ^^^^^
PP
is the preceding string, FF
is the following string and the party hats indicate which substrings are to be matched. (In the example given in the question key :
is the preceding string and -
is the following string.) I have assumed that PP
and FF
are preceded and followed by word boundaries (so that PPA
and FF8
are not matched).
My assumptions, as reflected by the party hats, are as follows:
PP
may be preceded by one (or more) FF
substrings, which, if present, are disregarded;PP
is followed by one or more PP
s before FF
is encountered, the following PP
s are part of the substring between the preceding and following strings;PP
is followed by one or more FF
s before a PP
is encounter, the first FF
following PP
is considered to be the following string.Note that many of the answers here deal with only strings of the form
abc PP def FF ghi
^^^^^
or
abc PP def FF ghi PP jkl FF mno
^^^^^ ^^^^^
One may use a regular expression, code constructs, or a combination of the two to identify the substrings of interest. I make no judgement as to which approach is best. I will only present the following regular expression that will match the substrings of interest.
(?<=\bPP\b)(?:(?!\bFF\b).)*(?=\bFF\b)
I tested this with the PCRE (PHP) regex engine, but as the regex is not at all exotic, I am sure it will work with the .NET regex engine (which is very robust).
The regex engine performs the following operations:
(?<= : begin a positive lookbehind
\bPP\b : match 'PP'
) : end positive lookbehind
(?: : begin a non-capture group
(?! : begin a negative lookahead
\bFF\b : match 'FF'
) : end negative lookahead
. : match any character
) : end non-capture group
* : execute non-capture group 0+ times
(?= : begin positive lookahead
\bFF\b : match 'FF'
) : end positive lookahead
This technique, of matching one character at a time, following the preceding string, until the character is F
and is followed by F
(or more generally, the character beings the string that constitutes the following string), is called Tempered Greedy Token Solution.
Naturally, the regex would have to be modified (if possible) if the assumptions I set out above are changed.
1. Move the cursor around for detailed explanations.
For get string between string's, I'm using this method:
public static class Extension
{
/// <summary>
/// Gets currently string between
/// </summary>
/// <param name="word">Currently string</param>
/// <param name="start">String left</param>
/// <param name="end">String right</param>
/// <returns>String between start and end</returns>
/// <example>The string "value (4815162342)" use Between("(",")") generates in method: "4815162342"</example>
public static string Between(this string word, string start, string end)
{
if (start.Equals(end))
throw new ArgumentException("Start string can't equals a end string.");
int startIndex = word.LastIndexOf(start) + 1;
int endIndex = word.LastIndexOf(end) - 1 - word.LastIndexOf(start);
return word.Substring(startIndex, endIndex);
}
}
If you want to handle multiple occurrences of substring pairs, it won't be easy without RegEx:
Regex.Matches(input ?? String.Empty, "(?=key : )(.*)(?<= - )", RegexOptions.Singleline);
input ?? String.Empty
avoids argument null exception?=
keeps 1st substring and?<=
keeps 2nd substringRegexOptions.Singleline
allows newline between substring pair
If order & occurrence count of substrings doesn't matter, this quick & dirty one may be an option:
var parts = input?.Split(new string[] { "key : ", " - " }, StringSplitOptions.None);
string result = parts?.Length >= 3 ? result[1] : input;
At least it avoids most exceptions, by returning the original string if none/single substring match.
You already have some good answers and I realize the code I am providing is far from the most efficient and clean. However, I thought it might be useful for educational purposes. We can use pre-built classes and libraries all day long. But without understanding the inner-workings, we are simply mimicking and repeating and will never learn anything. This code works and is more basic or "virgin" than some of the others:
char startDelimiter = ':';
char endDelimiter = '-';
Boolean collect = false;
string parsedString = "";
foreach (char c in originalString)
{
if (c == startDelimiter)
collect = true;
if (c == endDelimiter)
collect = false;
if (collect == true && c != startDelimiter)
parsedString += c;
}
You end up with your desired string assigned to the parsedString variable. Keep in mind that it will also capture proceeding and preceding spaces. Remember that a string is simply an array of characters that can be manipulated like other arrays with indices etc.
Take care.
As I always say nothing is impossible:
string value = "super exemple of string key : text I want to keep - end of my string";
Regex regex = new Regex(@"(key \: (.*?) _ )");
Match match = regex.Match(value);
if (match.Success)
{
Messagebox.Show(match.Value);
}
Remeber that should add reference of System.Text.RegularExpressions
Hope That I Helped.
Something like this perhaps
private static string Between(string text, string from, string to)
{
return text[(text.IndexOf(from)+from.Length)..text.IndexOf(to, text.IndexOf(from))];
}
getStringBetween(startStr, endStr, fullStr) {
string startIndex = fullStr.indexOf(startStr);
string endIndex= fullStr.indexOf(endStr);
return fullStr.substring(startIndex + startStr.length, endIndex);
}
Here it is;
/// <summary>
///
/// </summary>
/// <param name="line"></param>
/// <param name="begin_tag"></param>
/// <param name="end_tag"></param>
/// <param name="lastIndexOfEndTag"></param>
/// <returns></returns>
private string getBetween(string line, string begin_tag, string end_tag, bool lastIndexOfEndTag = false, bool returnNullIfTagsNotExists = false)
{
if (!string.IsNullOrEmpty(line) && !string.IsNullOrEmpty(begin_tag) && !string.IsNullOrEmpty(end_tag))
{
// 1 2 3 4 5 6 7
//0123456789012345678901234567890123456789012345678901234567890123456789012
//StdErrorData: Duration: 01:59:54.88, start: 0.000000, bitrate: 557 kb/s
int startIndex = line.IndexOf(begin_tag);
if (startIndex >= 0)
{
startIndex += begin_tag.Length;
}
else
{
if (returnNullIfTagsNotExists)
{
return null;
}
else
{
startIndex = 0;
}
}
int endIndex = lastIndexOfEndTag ?
line.LastIndexOf(end_tag, startIndex)
: line.IndexOf(end_tag, startIndex);
if (endIndex > startIndex)
{
return line.Substring(startIndex, endIndex - startIndex);
}
else
{
if (returnNullIfTagsNotExists)
{
return null;
}
else
{
return line.Substring(startIndex);
}
}
}
return null;
}
Test;
string r = getBetween("StdErrorData: Duration: 01:59:54.88, start: 0.000000, bitrate: 557 kb/s", "Duration:", ",");
Console.WriteLine($"<{r}>");
//< 01:59:54.88>
Here is the extension method in case anyone interested in keeping the start and end text as well.
public static string SubstringBetween(this string text, string start, string end, bool keepStartEndText = false)
{
var startIndex = text.IndexOf(start);
var endIndex = text.LastIndexOf(end);
if (keepStartEndText)
return text.Substring(startIndex, (endIndex + end.Length) - startIndex);
else
return text.Substring(startIndex + start.Length, endIndex - (startIndex + start.Length));
}
public static string ExtractBetweenTwoStrings(string FullText, string StartString, string EndString, bool IncludeStartString, bool IncludeEndString)
{
try { int Pos1 = FullText.IndexOf(StartString) + StartString.Length; int Pos2 = FullText.IndexOf(EndString, Pos1); return ((IncludeStartString) ? StartString : "")
+ FullText.Substring(Pos1, Pos2 - Pos1) + ((IncludeEndString) ? EndString : ""); } catch (Exception ex) { return ex.ToString(); } //return ""; }
}
credit to: https://www.c-sharpcorner.com/blogs/how-to-extract-a-string-lies-between-two-strings-in-c-sharpnet1