0

I have a text file with some data like this:

:20:220112REG063a1
:23B:CRED
.
.
:20:220112REG064
:23B:CRED
.
.
:20:220112REG077
:23B:CRED

I want to find each instance of the line starting with ":20:" and replace the entire line with a new string.

The code I have is as follows:

    rx = ":20:(.*)\r\n";

    for (var m = Regex.Match(fileToString, rx); m.Success; m = m.NextMatch())
    {
        tag20 = createTransactionReferenceNumber();
        fileToString = $"{fileToString.Substring(0, m.Index)}" + tag20 +  $"{fileToString.Substring(m.Index + m.Length)}";
    }

The above successfully replaces the first instance of the line but subsequent lines are "butchered". I am not sure how to fix this.

5
  • 1
    Did you want to use one of the regex.Replace() methods which takes a MatchEvaluator argument? learn.microsoft.com/en-us/dotnet/api/… Commented Feb 2, 2022 at 2:37
  • 2
    Just guessing since I don't know C#, but it appears you can't modify the very string that you are currently iterating on as the calculated indexes become outdated at best. I'd recommend loading the file as an array of lines, looping over the lines, and running Regex.Match separately on each line. Commented Feb 2, 2022 at 2:38
  • @JeremyLakeman can you please help me with some sample code for me to test? Thanks Commented Feb 2, 2022 at 3:17
  • I haven't used it before.... But perhaps like this? fileToString = Regex.Replace(fileToString, rx, m => createTransactionReferenceNumber()); or do you need to return $":20:{createTransactionReferenceNumber()}\r\n" ? Commented Feb 2, 2022 at 5:46
  • When you change the string you're matching from the Regex match is reset. Commented Feb 2, 2022 at 7:17

1 Answer 1

2

Looks to me like you're making life very complex. It would be lower resource usage and more performant to do something like:

public IEnumerable<string> ReadFileAndChangeOnTheFly(string filepath){

  foreach(var line in File.ReadLines(filepath)){
    if(line.StartsWith(":20:"))
      yield return createTransactionReferenceNumber();
    else
      yield return line;
  }

}

If your file is already read into a string and you can't do anything about that:

public IEnumerable<string> ReadStringAndChangeOnTheFly(string fileContent){

  var sr = new StringReader(fileContent);
  for(var line = sr.ReadLine(); line != null; line = sr.ReadLine())
  {
    if(line.StartsWith(":20:"))
      yield return createTransactionReferenceNumber();
    else
      yield return line;
  }

}

If you wanted all the lines of the file as an array:

var arr = ReadFileAndChangeOnTheFly("path here").ToArray();

If you wanted all the file as a single string:

var str = string.Join(Environment.NewLine, ReadFileAndChangeOnTheFly("path here"));

(Or ReadString... as appropriate)


If you want a "read the whole file into mem" approach it's very similar:

public string[] ReadFileAndChange(string filepath){

  var lines = File.ReadAllLines(filepath);
  for(int x = 0; x < lines.Length; x++){
    if(lines[x].StartsWith(":20:"))
      lines[x] = createTransactionReferenceNumber();
  }
  return lines;
}

If your file is already read into a string, change the ReadAllLines call for a Split call

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.