Find each instance and replace with unique value in string - c#

I have some text in a string as below:
{121:SOMETHING1}}{4:
.
.
.
{121:SOMETHING2}}{4:
.
.
.
{121:SOMETHING3}}{4:
I want to sequentially find and replace the value between 121: and the first }. I can successfully do this using the following code in C#
var rx = #"121:(?<value>[\s\S]+?)}";
string temp = tag121;
string stringToChange = //as above
for (var m = Regex.Match(stringToChange , rx); m.Success; m = m.NextMatch())
{
temp = generateUniqueValue()
stringToChange= Regex.Replace(stringToChange, m.Value, temp);
}
However, if instead of having different values between 121: and } I have exactly the same value for all the tags e.g instead of SOMETHING1, SOMETHING 2 etc, I just have SOMETHING for all the lines, then this code does not work. It ends up setting just one value for all the lines instead of unique values for each.

When all the lines in the string are all {121:SOMETHING}}{4:, the first cycle of the loop already replaced every SOMETHING in the string to first call result of generateUniqueValue(). You can see that happening by printing out stringToChange in the end of every for-loop cycle. (A good way to debug when working around regex, too)
You need to consider a new approach or look at what you trying to achieve again:
Is it acceptable that there are at least 2 lines with same value in the input?
Should lines with same values be replaced into different UniqueValue?
If answers to both questions are yes, one approach I suggest is replace line by line. Not optimal I guess though...
Split the string by lines. String.Split("\\n") Maybe?
Foreach through that split string array.
Find part to replace by regex {121:([^}]+)} - Group 1 of the match is the string you need to replace.
After foreach loop, concat the array into one single string again.
Reference:
Match.Groups

Related

Split the str-11-str and take only middle values

I have a string as you can see below. What the easiest and best way to take the middle value only.
123456789-11-abcd
So, I just want to take the middle value which is in between two (-).I know we can split on - and then we can store the string array and then find the right string but that will lengthy. Is there any easies way.
TIA
input_value = '123456789-11-abcd' # Consider this as a string
Split input_value by '-' and it will generate an list say Split_list
print second element from the Split_list
output_value = Split_list[1]
print(output_value) # Required Output

Splitting large string in c# and adding values in it to a List

I have a string as shown below
string names = "<?startname; Max?><?startname; Alex?><?startname; Rudy?>";
is there any way I can split this string and add Max , Alex and Rudy into a separate list ?
Sure, split on two strings (all that consistently comes before, and all that consistently comes after) and specify that you want Split to remove the empties:
var r = names.Split(new[]{ "<?startname; ", "?>" }, StringSplitOptions.RemoveEmptyEntries);
If you take out the RemoveEmptyEntries it will give you a more clear idea of how the splitting is working, but in essence without it you'd get your names interspersed with array entries that are empty strings because split found a delimiter (the <?...) immediately following another (the ?>) with an empty string between the delimiters
You can read the volumes of info about this form of split here - that's a direct link to netcore3.1, you can change your version in the table of contents - this variant of Split has been available since framework2.0
You did also say "add to a separate list" - didn't see any code for that so I guess you will either be happy to proceed with r here being "a separate list" (an array actually, but probably adequately equivalent and easy to convert with LINQ's ToList() if not) or if you have another list of names (that really is a List<string>) then you can thatList.AddRange(r) it
Another Idea is to use Regex
The following regex should work :
(?<=; )(.*?)(?=\s*\?>)

Regex : Replace text between semicolons a certain amount of times

i'm a bit confused with regex, i have a line which looks like something like this :
test = "article;vendor;qty;desc;price1;price2"
and what i'm trying to do is to only get price1.
I'm currently using this function :
Regex.Replace(test, #".*;[^;]*;", "");
which permit me to get price2 but I can't see how I can isolate price1.
Have you consider just using a String.Split() call instead to break your current semi-colon delimited string into an array :
var input = "article;vendor;qty;desc;price1;price2";
var output = input.Split(';');
And then you could simply access your value by its index :
var result = output[4]; // yields "price1"
You will only want to use a Regular Expression if there is a specific pattern that you can use to match and select exactly what you are looking for, but for delimited lists, the String.Split() method will usually make things easier (especially if there is nothing to uniquely identify the item you are trying to pull from the list).
Use the following regex:
(?:[^;]*;){4}([^;]*);
And replace the first match group.

Regex to select all commas up to a specific character

I am having a terrible time with regular expressions. Its terrible for me to admit, but I just don't use them enough to be really good when I need to be. Basically due to the way our application runs, I have the contents of a .csv file pulled out into a string. I need to essentially insert a new row above and below what already exists. The amount of columns can change depending on the report. What I would like to do is grab all commas without any other characters (including whitespace) up to the first set of \r\n in the string. This way I have all the columns and I can insert a blank row up top and populate the columns with what I need. Here is an example of the .csv text:
"Date, Account Code, Description, Amount\r\n23-Apr-13,12345,Account1,$12345\r\n"
What I would like the regex to grab:
",,," or ",,,\r\n"
I just cannot seem to get this. Thank you.
You don't need a regex for this.
string firstLine = file.ReadLines().First();
int numCommas = firstLine.Count(c => c == ',');
string commaString = new String(',', numCommas);
If you don't have access to file.ReadLines() method, you can use the following from this link:
string firstline = test.Substring(0, test.IndexOf(Environment.NewLine));
You actually don't need to complicate your code with Regular Epressions to accomplish what you want: to count the columns.
Here's an extremely simple method:
String textline = csvtext.Substring(0, csvtext.IndexOfAny(Environment.NewLine.ToCharArray()));
int columns = textline.Split(',').Length;
Now the columns variable has your total number of columns.
The first line grabs just the first line out of the CSV text. The second line splits that text into an array separated by commas (,), and returns the total number.
you can make use the below regex
(?<=[\d\w\s])(\r|\n|,)(?=[\d\w\s\W])
to match , and new line characters,
Use can make use of Regex.Replace("inputstring","regexpattern","replacechar", RegexOptions.IgnoreCase)
This can be done by string operations itself
string[] strs= inputstr.split(new string[]{"\n","\r",","}, StringSplitOptions.RemoveEmptyEntries);
foreach(string str in strs)
{
// do you part
}

Replacing part of text in richtextbox

I need to compare a value in a string to what user typed in a richtextbox.
For example: if a richtextbox holds string rtbText = "aaaka" and I compare this to another variable string comparable = "ka"(I want it to compare backwards). I want the last 2 letters from rtbText (comparable has only 2 letters) to be replaced with something that was predetermined(doesn't really matter what).
So rtbText should look like this:
rtbText = "aaa(something)"
This doesn't really have to be compared it can just count letters in comparable and based on that it can remove 2 letters from rtbText and replace them with something else.
UPDATE:
Here is what I have:
int coLen = comparable.Length;
comparable = null;
TextPointer caretBack = rtb.CaretPosition.GetPositionAtOffset(coLen, LogicalDirection.Backward);
TextRange rtbText = new TextRange(rtb.CaretPosition, caretBack);
string text = rtbText.Text;
rtbText returns an empty string or I get an error for everything longer than 3 characters. What am I doing wrong?
Let me elaborate it a little bit further. I have a listbox that holds replacements for values that user types in rtb. The values(replacements) are coming from there, meaning that I don't really need to go through the whole text to check values. I just need to check the values right before caret. I am comparing these values to what I have stored in another variable (comparable).
Please let me know if you don't understand something.
I did my best to explain what needs to be done.
Thank you
You could use Regex.Replace.
// this replaces all occurances of "ka" with "Replacement"
Regex replace = new Regex("ka");
string result = replace.Replace("aaaka","Replacemenet");
gumenimeda, I had similar problems few weeks ago. I found my self doing the following (I asume you will have more than one occurance in the RichTextBox that you will need to change), note that I did it for Windows Forms where I have access directly to the Rtf text of the control, not quite sure if it will work well in your scenario:
I find all the occurancies of the string (using IndexOf for example) and store them in a List for example.
Sort the list in descending order (max index goes first, the one before him second, etc)
Start replacing the occurancies directly in the RichTextBox, by removing the characters I don't need and appending the characters I need.
The sorting in step 2 is necessary as we always want to start from the last occurance going up to the first. Starting from the first occurance or any other and going down will have an unpleasant surprise - if the length of the chunk you want to remove and the length of the chunk you want to append are different in length, the string will be modified and all other occurancies will be invalid (for example if the second occurance was in at position 12 and your new string is 2 characters longer than the original, it will become 14th). This is not an issue if we go from the last to the first occurance as the change in string will not affect the next occurance in the list).
Ofcourse I can not be sure that this is the fastest way that can be used to achieve the desired result. It's just what I came up with and what worked for me.
Good luck!

Categories