Related
I have this string: ABCDEFGHIJ
I need to replace from position 4 to position 5 with the string ZX
It will look like this: ABCZXFGHIJ
But not to use with string.replace("DE","ZX") - I need to use with position
How can I do it?
string s = "ABCDEFGH";
s= s.Remove(3, 2).Insert(3, "ZX");
The easiest way to add and remove ranges in a string is to use the StringBuilder.
var theString = "ABCDEFGHIJ";
var aStringBuilder = new StringBuilder(theString);
aStringBuilder.Remove(3, 2);
aStringBuilder.Insert(3, "ZX");
theString = aStringBuilder.ToString();
An alternative is to use String.Substring, but I think the StringBuilder code gets more readable.
ReplaceAt(int index, int length, string replace)
Here's an extension method that doesn't use StringBuilder or Substring. This method also allows the replacement string to extend past the length of the source string.
//// str - the source string
//// index- the start location to replace at (0-based)
//// length - the number of characters to be removed before inserting
//// replace - the string that is replacing characters
public static string ReplaceAt(this string str, int index, int length, string replace)
{
return str.Remove(index, Math.Min(length, str.Length - index))
.Insert(index, replace);
}
When using this function, if you want the entire replacement string to replace as many characters as possible, then set length to the length of the replacement string:
"0123456789".ReplaceAt(7, 5, "Hello") = "0123456Hello"
Otherwise, you can specify the amount of characters that will be removed:
"0123456789".ReplaceAt(2, 2, "Hello") = "01Hello456789"
If you specify the length to be 0, then this function acts just like the insert function:
"0123456789".ReplaceAt(4, 0, "Hello") = "0123Hello456789"
I guess this is more efficient since the StringBuilder class need not be initialized and since it uses more basic operations. Please correct me if I am wrong. :)
If you care about performance, then the thing you want to avoid here are allocations. And if you're on .Net Core 2.1+, then you can, by using the string.Create method:
public static string ReplaceAt(this string str, int index, int length, string replace)
{
return string.Create(str.Length - length + replace.Length, (str, index, length, replace),
(span, state) =>
{
state.str.AsSpan().Slice(0, state.index).CopyTo(span);
state.replace.AsSpan().CopyTo(span.Slice(state.index));
state.str.AsSpan().Slice(state.index + state.length).CopyTo(span.Slice(state.index + state.replace.Length));
});
}
This approach is harder to understand than the alternatives, but it's the only one that will allocate only one object per call: the newly created string.
Use String.Substring() (details here) to cut left part, then your replacement, then right part. Play with indexes until you get it right :)
Something like:
string replacement=original.Substring(0,start)+
rep+original.Substring(start+rep.Length);
string s = "ABCDEFG";
string t = "st";
s = s.Remove(4, t.Length);
s = s.Insert(4, t);
As an extension method.
public static class StringBuilderExtension
{
public static string SubsituteString(this string OriginalStr, int index, int length, string SubsituteStr)
{
return new StringBuilder(OriginalStr).Remove(index, length).Insert(index, SubsituteStr).ToString();
}
}
You could try something link this:
string str = "ABCDEFGHIJ";
str = str.Substring(0, 2) + "ZX" + str.Substring(5);
Like other have mentioned the Substring() function is there for a reason:
static void Main(string[] args)
{
string input = "ABCDEFGHIJ";
string output = input.Overwrite(3, "ZX"); // 4th position has index 3
// ABCZXFGHIJ
}
public static string Overwrite(this string text, int position, string new_text)
{
return text.Substring(0, position) + new_text + text.Substring(position + new_text.Length);
}
Also I timed this against the StringBuilder solution and got 900 tics vs. 875. So it is slightly slower.
Yet another
public static string ReplaceAtPosition(this string self, int position, string newValue)
{
return self.Remove(position, newValue.Length).Insert(position, newValue);
}
With the help of this post, I create following function with additional length checks
public string ReplaceStringByIndex(string original, string replaceWith, int replaceIndex)
{
if (original.Length >= (replaceIndex + replaceWith.Length))
{
StringBuilder rev = new StringBuilder(original);
rev.Remove(replaceIndex, replaceWith.Length);
rev.Insert(replaceIndex, replaceWith);
return rev.ToString();
}
else
{
throw new Exception("Wrong lengths for the operation");
}
}
All others answers don't work if the string contains Unicode char (like Emojis) because an Unicode char weight more bytes than a char.
Example : the emoji '🎶' converted to bytes, will weight the equivalent of 2 chars. So, if the unicode char is placed at the beginning of your string, offset parameter will be shifted).
With this topic, i extend the StringInfo class to Replace by position keeping the Nick Miller's algorithm to avoid that :
public static class StringInfoUtils
{
public static string ReplaceByPosition(this string str, string replaceBy, int offset, int count)
{
return new StringInfo(str).ReplaceByPosition(replaceBy, offset, count).String;
}
public static StringInfo ReplaceByPosition(this StringInfo str, string replaceBy, int offset, int count)
{
return str.RemoveByTextElements(offset, count).InsertByTextElements(offset, replaceBy);
}
public static StringInfo RemoveByTextElements(this StringInfo str, int offset, int count)
{
return new StringInfo(string.Concat(
str.SubstringByTextElements(0, offset),
offset + count < str.LengthInTextElements
? str.SubstringByTextElements(offset + count, str.LengthInTextElements - count - offset)
: ""
));
}
public static StringInfo InsertByTextElements(this StringInfo str, int offset, string insertStr)
{
if (string.IsNullOrEmpty(str?.String))
return new StringInfo(insertStr);
return new StringInfo(string.Concat(
str.SubstringByTextElements(0, offset),
insertStr,
str.LengthInTextElements - offset > 0 ? str.SubstringByTextElements(offset, str.LengthInTextElements - offset) : ""
));
}
}
string myString = "ABCDEFGHIJ";
string modifiedString = new StringBuilder(myString){[3]='Z', [4]='X'}.ToString();
Let me explain my solution.
Given the problem statement of altering a string in its two specific position (“position 4 to position 5”) with two character ‘Z’ and ‘X’ and the ask is to use the position index to alter the string and not string Replace() method(may be because of the possibility of repetition of some characters in the actual string), I would prefer to use minimalist approach to achieve the goal over using Substring() and string Concat() or string Remove() and Insert() approach. Though all those solutions will serve the purpose in attaining the same goal, but it just depends on personal choice and philosophy of settling with minimalist approach.
Coming back to my solution mention above, if we take a closer look of string and StringBuilder, both of them internally treats a given string as an array of characters. If we look at the implementation of StringBuilder it maintains an internal variable something like “internal char[] m_ChunkChars;” to capture the given string. Now since this is an internal variable, we cannot directly access the same. For external world, to be able to access and alter that character array, StringBuilder exposes them through indexer property which looks something like below
[IndexerName("Chars")]
public char this[int index]
{
get
{
StringBuilder stringBuilder = this;
do
{
// … some code
return stringBuilder.m_ChunkChars[index1];
// … some more code
}
}
set
{
StringBuilder stringBuilder = this;
do
{
//… some code
stringBuilder.m_ChunkChars[index1] = value;
return;
// …. Some more code
}
}
}
My solution mentioned above leverage this indexer capability to directly alter the internally maintained character array which IMO is efficient and minimalist.
BTW; we can rewrite the above solution more elaborately something like below
string myString = "ABCDEFGHIJ";
StringBuilder tempString = new StringBuilder(myString);
tempString[3] = 'Z';
tempString[4] = 'X';
string modifiedString = tempString.ToString();
In this context also would like to mention that in case of string it also have indexer property as a means to expose its internal character array, but in this case it only has Getter property (and no Setter) as string is immutable in nature. And that is why we need to use StringBuilder to alter the character array.
[IndexerName("Chars")]
public extern char this[int index] { [SecuritySafeCritical, __DynamicallyInvokable, MethodImpl(MethodImplOptions.InternalCall)] get; }
And last but not the least this solution is only best fit for this specific problem where the ask is to replace only few characters with a known position index upfront. It may not be the best fit when the requirement is to alter a fairly lengthy string i.e. number of characters to alter are large in numbers.
I was looking for a solution with following requirements:
use only a single, one-line expression
use only system builtin methods (no custom implemented utility)
Solution 1
The solution that best suits me is this:
// replace `oldString[i]` with `c`
string newString = new StringBuilder(oldString).Replace(oldString[i], c, i, 1).ToString();
This uses StringBuilder.Replace(oldChar, newChar, position, count)
Solution 2
The other solution that satisfies my requirements is to use Substring with concatenation:
string newString = oldStr.Substring(0, i) + c + oldString.Substring(i+1, oldString.Length);
This is OK too. I guess it's not as efficient as the first one performance wise (due to unnecessary string concatenation). But premature optimization is the root of all evil.
So pick the one that you like the most :)
hello this code helps me:
var theString = "ABCDEFGHIJ";
var aStringBuilder = new StringBuilder(theString);
aStringBuilder.Remove(3, 2);
aStringBuilder.Insert(3, "ZX");
theString = aStringBuilder.ToString();
It's better to use the String.substr().
Like this:
ReplString = GivenStr.substr(0, PostostarRelStr)
+ GivenStr(PostostarRelStr, ReplString.lenght());
String timestamp = "2019-09-18 21.42.05.000705";
String sub1 = timestamp.substring(0, 19).replace('.', ':');
String sub2 = timestamp.substring(19, timestamp.length());
System.out.println("Original String "+ timestamp);
System.out.println("Replaced Value "+ sub1+sub2);
Here is a simple extension method:
public static class StringBuilderExtensions
{
public static StringBuilder Replace(this StringBuilder sb, int position, string newString)
=> sb.Replace(position, newString.Length, newString);
public static StringBuilder Replace(this StringBuilder sb, int position, int length, string newString)
=> (newString.Length <= length)
? sb.Remove(position, newString.Length).Insert(position, newString)
: sb.Remove(position, length).Insert(position, newString.Substring(0, length));
}
Use it like this:
var theString = new string(' ', 10);
var sb = new StringBuilder(theString);
sb.Replace(5, "foo");
return sb.ToString();
I do this
Dim QTT As Double
If IsDBNull(dr.Item(7)) Then
QTT = 0
Else
Dim value As String = dr.Item(7).ToString()
Dim posicpoint As Integer = value.LastIndexOf(".")
If posicpoint > 0 Then
Dim v As New Text.StringBuilder(value)
v.Remove(posicpoint, 1)
v.Insert(posicpoint, ",")
QTT = Convert.ToDouble(v.ToString())
Else
QTT = Convert.ToDouble(dr.Item(7).ToString())
End If
Console.WriteLine(QTT.ToString())
End If
Suppose we know the index of string to be replace.
string s = "ABCDEFGDEJ";
string z = "DE";
int i = s.IndexOf(z);
if(i == 3)
s = s.Remove(3,z.Length).Insert(3,"ZX");
//s = ABCZXFGDEJ
I believe the simplest way would be this:(without stringbuilder)
string myString = "ABCDEFGHIJ";
char[] replacementChars = {'Z', 'X'};
byte j = 0;
for (byte i = 3; i <= 4; i++, j++)
{
myString = myString.Replace(myString[i], replacementChars[j]);
}
This works because a variable of type string can be treated as an array of char variables.
You can, for example refer to the second character of a string variable with name "myString" as myString[1]
I have a string of text and want to ensure that it contains at most one single occurrence of a specific character (,). Therefore I want to keep the first one, but simply remove all further occurrences of that character.
How could I do this the most elegant way using C#?
This works, but not the most elegant for sure :-)
string a = "12,34,56,789";
int pos = 1 + a.IndexOf(',');
return a.Substring(0, pos) + a.Substring(pos).Replace(",", string.Empty);
You could use a counter variable and a StringBuilder to create the new string efficiently:
var sb = new StringBuilder(text.Length);
int maxCount = 1;
int currentCount = 0;
char specialChar = ',';
foreach(char c in text)
if(c != specialChar || ++currentCount <= maxCount)
sb.Append(c);
text = sb.ToString();
This approach is not the shortest but it's efficient and you can specify the char-count to keep.
Here's a more "elegant" way using LINQ:
int commasFound = 0; int maxCommas = 1;
text = new string(text.Where(c => c != ',' || ++commasFound <= maxCommas).ToArray());
I don't like it because it requires to modify a variable from a query, so it's causing a side-effect.
Regular expressions are elegant, right?
Regex.Replace("Eats, shoots, and leaves.", #"(?<=,.*),", "");
This replaces every comma, as long as there is a comma before it, with nothing.
(Actually, it's probably not elegant - it may only be one line of code, but it may also be O(n^2)...)
If you don't deal with large strings and you reaaaaaaly like Linq oneliners:
public static string KeepFirstOccurence (this string #string, char #char)
{
var index = #string.IndexOf(#char);
return String.Concat(String.Concat(#string.TakeWhile(x => #string.IndexOf(x) < index + 1)), String.Concat(#string.SkipWhile(x=>#string.IndexOf(x) < index)).Replace(#char.ToString(), ""));
}
You could write a function like the following one that would split the string into two sections based on the location of what you were searching (via the String.Split() method) for and it would only remove matches from the second section (using String.Replace()) :
public static string RemoveAllButFirst(string s, string stuffToRemove)
{
// Check if the stuff to replace exists and if not, return the original string
var locationOfStuff = s.IndexOf(stuffToRemove);
if (locationOfStuff < 0)
{
return s;
}
// Calculate where to pull the first string from and then replace the rest of the string
var splitLocation = locationOfStuff + stuffToRemove.Length;
return s.Substring(0, splitLocation) + (s.Substring(splitLocation)).Replace(stuffToRemove,"");
}
You could simply call it by using :
var output = RemoveAllButFirst(input,",");
A prettier approach might actually involve building an extension method that handled this a bit more cleanly :
public static class StringExtensions
{
public static string RemoveAllButFirst(this string s, string stuffToRemove)
{
// Check if the stuff to replace exists and if not, return the
// original string
var locationOfStuff = s.IndexOf(stuffToRemove);
if (locationOfStuff < 0)
{
return s;
}
// Calculate where to pull the first string from and then replace the rest of the string
var splitLocation = locationOfStuff + stuffToRemove.Length;
return s.Substring(0, splitLocation) + (s.Substring(splitLocation)).Replace(stuffToRemove,"");
}
}
which would be called via :
var output = input.RemoveAllButFirst(",");
You can see a working example of it here.
static string KeepFirstOccurance(this string str, char c)
{
int charposition = str.IndexOf(c);
return str.Substring(0, charposition + 1) +
str.Substring(charposition, str.Length - charposition)
.Replace(c, ' ').Trim();
}
Pretty short with Linq; split string into chars, keep distinct set and join back to a string.
text = string.Join("", text.Select(c => c).Distinct());
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);
}
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.
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
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.
or
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:
The first substring PP may be preceded by one (or more) FF substrings, which, if present, are disregarded;
If PP is followed by one or more PPs before FF is encountered, the following PPs are part of the substring between the preceding and following strings;
If PP is followed by one or more FFs 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)
Start your engine!1
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.
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 substring
RegexOptions.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.
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);
}
}
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
I have this string: ABCDEFGHIJ
I need to replace from position 4 to position 5 with the string ZX
It will look like this: ABCZXFGHIJ
But not to use with string.replace("DE","ZX") - I need to use with position
How can I do it?
string s = "ABCDEFGH";
s= s.Remove(3, 2).Insert(3, "ZX");
The easiest way to add and remove ranges in a string is to use the StringBuilder.
var theString = "ABCDEFGHIJ";
var aStringBuilder = new StringBuilder(theString);
aStringBuilder.Remove(3, 2);
aStringBuilder.Insert(3, "ZX");
theString = aStringBuilder.ToString();
An alternative is to use String.Substring, but I think the StringBuilder code gets more readable.
ReplaceAt(int index, int length, string replace)
Here's an extension method that doesn't use StringBuilder or Substring. This method also allows the replacement string to extend past the length of the source string.
//// str - the source string
//// index- the start location to replace at (0-based)
//// length - the number of characters to be removed before inserting
//// replace - the string that is replacing characters
public static string ReplaceAt(this string str, int index, int length, string replace)
{
return str.Remove(index, Math.Min(length, str.Length - index))
.Insert(index, replace);
}
When using this function, if you want the entire replacement string to replace as many characters as possible, then set length to the length of the replacement string:
"0123456789".ReplaceAt(7, 5, "Hello") = "0123456Hello"
Otherwise, you can specify the amount of characters that will be removed:
"0123456789".ReplaceAt(2, 2, "Hello") = "01Hello456789"
If you specify the length to be 0, then this function acts just like the insert function:
"0123456789".ReplaceAt(4, 0, "Hello") = "0123Hello456789"
I guess this is more efficient since the StringBuilder class need not be initialized and since it uses more basic operations. Please correct me if I am wrong. :)
If you care about performance, then the thing you want to avoid here are allocations. And if you're on .Net Core 2.1+, then you can, by using the string.Create method:
public static string ReplaceAt(this string str, int index, int length, string replace)
{
return string.Create(str.Length - length + replace.Length, (str, index, length, replace),
(span, state) =>
{
state.str.AsSpan().Slice(0, state.index).CopyTo(span);
state.replace.AsSpan().CopyTo(span.Slice(state.index));
state.str.AsSpan().Slice(state.index + state.length).CopyTo(span.Slice(state.index + state.replace.Length));
});
}
This approach is harder to understand than the alternatives, but it's the only one that will allocate only one object per call: the newly created string.
Use String.Substring() (details here) to cut left part, then your replacement, then right part. Play with indexes until you get it right :)
Something like:
string replacement=original.Substring(0,start)+
rep+original.Substring(start+rep.Length);
string s = "ABCDEFG";
string t = "st";
s = s.Remove(4, t.Length);
s = s.Insert(4, t);
As an extension method.
public static class StringBuilderExtension
{
public static string SubsituteString(this string OriginalStr, int index, int length, string SubsituteStr)
{
return new StringBuilder(OriginalStr).Remove(index, length).Insert(index, SubsituteStr).ToString();
}
}
You could try something link this:
string str = "ABCDEFGHIJ";
str = str.Substring(0, 2) + "ZX" + str.Substring(5);
Like other have mentioned the Substring() function is there for a reason:
static void Main(string[] args)
{
string input = "ABCDEFGHIJ";
string output = input.Overwrite(3, "ZX"); // 4th position has index 3
// ABCZXFGHIJ
}
public static string Overwrite(this string text, int position, string new_text)
{
return text.Substring(0, position) + new_text + text.Substring(position + new_text.Length);
}
Also I timed this against the StringBuilder solution and got 900 tics vs. 875. So it is slightly slower.
Yet another
public static string ReplaceAtPosition(this string self, int position, string newValue)
{
return self.Remove(position, newValue.Length).Insert(position, newValue);
}
With the help of this post, I create following function with additional length checks
public string ReplaceStringByIndex(string original, string replaceWith, int replaceIndex)
{
if (original.Length >= (replaceIndex + replaceWith.Length))
{
StringBuilder rev = new StringBuilder(original);
rev.Remove(replaceIndex, replaceWith.Length);
rev.Insert(replaceIndex, replaceWith);
return rev.ToString();
}
else
{
throw new Exception("Wrong lengths for the operation");
}
}
All others answers don't work if the string contains Unicode char (like Emojis) because an Unicode char weight more bytes than a char.
Example : the emoji '🎶' converted to bytes, will weight the equivalent of 2 chars. So, if the unicode char is placed at the beginning of your string, offset parameter will be shifted).
With this topic, i extend the StringInfo class to Replace by position keeping the Nick Miller's algorithm to avoid that :
public static class StringInfoUtils
{
public static string ReplaceByPosition(this string str, string replaceBy, int offset, int count)
{
return new StringInfo(str).ReplaceByPosition(replaceBy, offset, count).String;
}
public static StringInfo ReplaceByPosition(this StringInfo str, string replaceBy, int offset, int count)
{
return str.RemoveByTextElements(offset, count).InsertByTextElements(offset, replaceBy);
}
public static StringInfo RemoveByTextElements(this StringInfo str, int offset, int count)
{
return new StringInfo(string.Concat(
str.SubstringByTextElements(0, offset),
offset + count < str.LengthInTextElements
? str.SubstringByTextElements(offset + count, str.LengthInTextElements - count - offset)
: ""
));
}
public static StringInfo InsertByTextElements(this StringInfo str, int offset, string insertStr)
{
if (string.IsNullOrEmpty(str?.String))
return new StringInfo(insertStr);
return new StringInfo(string.Concat(
str.SubstringByTextElements(0, offset),
insertStr,
str.LengthInTextElements - offset > 0 ? str.SubstringByTextElements(offset, str.LengthInTextElements - offset) : ""
));
}
}
string myString = "ABCDEFGHIJ";
string modifiedString = new StringBuilder(myString){[3]='Z', [4]='X'}.ToString();
Let me explain my solution.
Given the problem statement of altering a string in its two specific position (“position 4 to position 5”) with two character ‘Z’ and ‘X’ and the ask is to use the position index to alter the string and not string Replace() method(may be because of the possibility of repetition of some characters in the actual string), I would prefer to use minimalist approach to achieve the goal over using Substring() and string Concat() or string Remove() and Insert() approach. Though all those solutions will serve the purpose in attaining the same goal, but it just depends on personal choice and philosophy of settling with minimalist approach.
Coming back to my solution mention above, if we take a closer look of string and StringBuilder, both of them internally treats a given string as an array of characters. If we look at the implementation of StringBuilder it maintains an internal variable something like “internal char[] m_ChunkChars;” to capture the given string. Now since this is an internal variable, we cannot directly access the same. For external world, to be able to access and alter that character array, StringBuilder exposes them through indexer property which looks something like below
[IndexerName("Chars")]
public char this[int index]
{
get
{
StringBuilder stringBuilder = this;
do
{
// … some code
return stringBuilder.m_ChunkChars[index1];
// … some more code
}
}
set
{
StringBuilder stringBuilder = this;
do
{
//… some code
stringBuilder.m_ChunkChars[index1] = value;
return;
// …. Some more code
}
}
}
My solution mentioned above leverage this indexer capability to directly alter the internally maintained character array which IMO is efficient and minimalist.
BTW; we can rewrite the above solution more elaborately something like below
string myString = "ABCDEFGHIJ";
StringBuilder tempString = new StringBuilder(myString);
tempString[3] = 'Z';
tempString[4] = 'X';
string modifiedString = tempString.ToString();
In this context also would like to mention that in case of string it also have indexer property as a means to expose its internal character array, but in this case it only has Getter property (and no Setter) as string is immutable in nature. And that is why we need to use StringBuilder to alter the character array.
[IndexerName("Chars")]
public extern char this[int index] { [SecuritySafeCritical, __DynamicallyInvokable, MethodImpl(MethodImplOptions.InternalCall)] get; }
And last but not the least this solution is only best fit for this specific problem where the ask is to replace only few characters with a known position index upfront. It may not be the best fit when the requirement is to alter a fairly lengthy string i.e. number of characters to alter are large in numbers.
I was looking for a solution with following requirements:
use only a single, one-line expression
use only system builtin methods (no custom implemented utility)
Solution 1
The solution that best suits me is this:
// replace `oldString[i]` with `c`
string newString = new StringBuilder(oldString).Replace(oldString[i], c, i, 1).ToString();
This uses StringBuilder.Replace(oldChar, newChar, position, count)
Solution 2
The other solution that satisfies my requirements is to use Substring with concatenation:
string newString = oldStr.Substring(0, i) + c + oldString.Substring(i+1, oldString.Length);
This is OK too. I guess it's not as efficient as the first one performance wise (due to unnecessary string concatenation). But premature optimization is the root of all evil.
So pick the one that you like the most :)
hello this code helps me:
var theString = "ABCDEFGHIJ";
var aStringBuilder = new StringBuilder(theString);
aStringBuilder.Remove(3, 2);
aStringBuilder.Insert(3, "ZX");
theString = aStringBuilder.ToString();
It's better to use the String.substr().
Like this:
ReplString = GivenStr.substr(0, PostostarRelStr)
+ GivenStr(PostostarRelStr, ReplString.lenght());
String timestamp = "2019-09-18 21.42.05.000705";
String sub1 = timestamp.substring(0, 19).replace('.', ':');
String sub2 = timestamp.substring(19, timestamp.length());
System.out.println("Original String "+ timestamp);
System.out.println("Replaced Value "+ sub1+sub2);
Here is a simple extension method:
public static class StringBuilderExtensions
{
public static StringBuilder Replace(this StringBuilder sb, int position, string newString)
=> sb.Replace(position, newString.Length, newString);
public static StringBuilder Replace(this StringBuilder sb, int position, int length, string newString)
=> (newString.Length <= length)
? sb.Remove(position, newString.Length).Insert(position, newString)
: sb.Remove(position, length).Insert(position, newString.Substring(0, length));
}
Use it like this:
var theString = new string(' ', 10);
var sb = new StringBuilder(theString);
sb.Replace(5, "foo");
return sb.ToString();
I do this
Dim QTT As Double
If IsDBNull(dr.Item(7)) Then
QTT = 0
Else
Dim value As String = dr.Item(7).ToString()
Dim posicpoint As Integer = value.LastIndexOf(".")
If posicpoint > 0 Then
Dim v As New Text.StringBuilder(value)
v.Remove(posicpoint, 1)
v.Insert(posicpoint, ",")
QTT = Convert.ToDouble(v.ToString())
Else
QTT = Convert.ToDouble(dr.Item(7).ToString())
End If
Console.WriteLine(QTT.ToString())
End If
Suppose we know the index of string to be replace.
string s = "ABCDEFGDEJ";
string z = "DE";
int i = s.IndexOf(z);
if(i == 3)
s = s.Remove(3,z.Length).Insert(3,"ZX");
//s = ABCZXFGDEJ
I believe the simplest way would be this:(without stringbuilder)
string myString = "ABCDEFGHIJ";
char[] replacementChars = {'Z', 'X'};
byte j = 0;
for (byte i = 3; i <= 4; i++, j++)
{
myString = myString.Replace(myString[i], replacementChars[j]);
}
This works because a variable of type string can be treated as an array of char variables.
You can, for example refer to the second character of a string variable with name "myString" as myString[1]
I want to replace the first occurrence in a given string.
How can I accomplish this in .NET?
string ReplaceFirst(string text, string search, string replace)
{
int pos = text.IndexOf(search);
if (pos < 0)
{
return text;
}
return text.Substring(0, pos) + replace + text.Substring(pos + search.Length);
}
Example:
string str = "The brown brown fox jumps over the lazy dog";
str = ReplaceFirst(str, "brown", "quick");
EDIT: As #itsmatt mentioned, there's also Regex.Replace(String, String, Int32), which can do the same, but is probably more expensive at runtime, since it's utilizing a full featured parser where my method does one find and three string concatenations.
EDIT2: If this is a common task, you might want to make the method an extension method:
public static class StringExtension
{
public static string ReplaceFirst(this string text, string search, string replace)
{
// ...same as above...
}
}
Using the above example it's now possible to write:
str = str.ReplaceFirst("brown", "quick");
As itsmatt said Regex.Replace is a good choice for this however to make his answer more complete I will fill it in with a code sample:
using System.Text.RegularExpressions;
...
Regex regex = new Regex("foo");
string result = regex.Replace("foo1 foo2 foo3 foo4", "bar", 1);
// result = "bar1 foo2 foo3 foo4"
The third parameter, set to 1 in this case, is the number of occurrences of the regex pattern that you want to replace in the input string from the beginning of the string.
I was hoping this could be done with a static Regex.Replace overload but unfortunately it appears you need a Regex instance to accomplish it.
Take a look at Regex.Replace.
using System.Text.RegularExpressions;
RegEx MyRegEx = new RegEx("F");
string result = MyRegex.Replace(InputString, "R", 1);
will find first F in InputString and replace it with R.
Taking the "first only" into account, perhaps:
int index = input.IndexOf("AA");
if (index >= 0) output = input.Substring(0, index) + "XQ" +
input.Substring(index + 2);
?
Or more generally:
public static string ReplaceFirstInstance(this string source,
string find, string replace)
{
int index = source.IndexOf(find);
return index < 0 ? source : source.Substring(0, index) + replace +
source.Substring(index + find.Length);
}
Then:
string output = input.ReplaceFirstInstance("AA", "XQ");
C# extension method that will do this:
public static class StringExt
{
public static string ReplaceFirstOccurrence(this string s, string oldValue, string newValue)
{
int i = s.IndexOf(oldValue);
return s.Remove(i, oldValue.Length).Insert(i, newValue);
}
}
In C# syntax:
int loc = original.IndexOf(oldValue);
if( loc < 0 ) {
return original;
}
return original.Remove(loc, oldValue.Length).Insert(loc, newValue);
Assumes that AA only needs to be replaced if it is at the very start of the string:
var newString;
if(myString.StartsWith("AA"))
{
newString ="XQ" + myString.Substring(2);
}
If you need to replace the first occurrence of AA, whether the string starts with it or not, go with the solution from Marc.
And because there is also VB.NET to consider, I would like to offer up:
Private Function ReplaceFirst(ByVal text As String, ByVal search As String, ByVal replace As String) As String
Dim pos As Integer = text.IndexOf(search)
If pos >= 0 Then
Return text.Substring(0, pos) + replace + text.Substring(pos + search.Length)
End If
Return text
End Function
One of the overloads of Regex.Replace takes an int for "The maximum number of times the replacement can occur". Obviously, using Regex.Replace for plain text replacement may seem like overkill, but it's certainly concise:
string output = (new Regex("AA")).Replace(input, "XQ", 1);
For anyone that doesn't mind a reference to Microsoft.VisualBasic, there is the Replace Method:
string result = Microsoft.VisualBasic.Strings.Replace("111", "1", "0", 2, 1); // "101"
This example abstracts away the substrings (but is slower), but is probably much fast than a RegEx:
var parts = contents.ToString().Split(new string[] { "needle" }, 2, StringSplitOptions.None);
return parts[0] + "replacement" + parts[1];
Updated extension method utilizing Span to minimize new string creation
public static string ReplaceFirstOccurrence(this string source, string search, string replace) {
int index = source.IndexOf(search);
if (index < 0) return source;
var sourceSpan = source.AsSpan();
return string.Concat(sourceSpan.Slice(0, index), replace, sourceSpan.Slice(index + search.Length));
}
With ranges and C# 10 we can do:
public static string ReplaceFirst(this string text, string search, string replace)
{
int pos = text.IndexOf(search, StringComparison.Ordinal);
return pos < 0 ? text : string.Concat(text[..pos], replace, text.AsSpan(pos + search.Length));
}
string abc = "AAAAX1";
if(abc.IndexOf("AA") == 0)
{
abc.Remove(0, 2);
abc = "XQ" + abc;
}