ratsstack
ratsstack

Reputation: 1021

Regex match and replace with different values

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.

Upvotes: 0

Views: 219

Answers (1)

Caius Jard
Caius Jard

Reputation: 74660

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

Upvotes: 2

Related Questions