简体   繁体   中英

Regex replace in a string that contains one substring and does not contain another substring

I have a text that looks like this:

[customer id = "1" name="Bob" ...]
[customer id="2" name="Adam" ...]
[customer id="3" ...]
[customer id = "4" name="Julia" ...]

I have a function that should add Name to the entry if Name is not specified:

string AddNameIfDoesNotSpecified(string text, string id, string name)
{
    return Regex.Replace(text,
                    $"id\\s*=\\s*\"{id}\"",
                    $"id=\"{id}\" name=\"{name}\"",
                    RegexOptions.IgnoreCase | RegexOptions.Compiled);
}

This works except that it does replace even if there is a name specified. How do I change regex to check if there is "name\\\\s*=" substring, and if it's there - do not do replacement?

Another thing that I need to implement is UpdatName method:

string UpdateNameIfSpecified(string text, string id, string oldName, string newName)
{
    return Regex.Replace(text,
                    $"id\\s*=\\s*\"{id}\" name\\s*=\\s*\"{oldName}\"",
                    $"id=\"{id}\" name=\"{newName}\"",
                    RegexOptions.IgnoreCase | RegexOptions.Compiled);
}

It works, but if we have other attributes between id and name like:

[customer id="5" gender="female" name="Marta" ...]

it's not going to work, how do I make it work in C# using regex? Should I use groups?

Examples:

AddNameIfDoesNotSpecified("[customer id = \"6\" ...]", "6", "Alex") 
               // output: "[customer id=\"6\" name=\"Alex\" ...]"

AddNameIfDoesNotSpecified("[customer id =\"7\" gender=\"male\" name=\"Greg\" ...]", "7", "Eric") 
               // output: "[customer id=\"7\" gender=\"male\" name=\"Greg\" ...]"

UpdateNameIfSpecified("[customer id = \"8\" ...]", "8", "Sam", "Don") 
           // output: "[customer id=\"8\" ...]"

UpdateNameIfSpecified("[customer id = \"9\" name=\"Lisa\" ...]", "9", "Lisa", "Carl") 
           // output: "[customer id=\"9\" name=\"Carl\" ...]"

UpdateNameIfSpecified("[customer id=\"10\" gender=\"female\" name=\"Megan\" ...]", "10", "Megan", "Amy") 
           // output: "[customer id=\"10\" gender=\"female\" name=\"Amy\" ...]"

UpdateNameIfSpecified("[customer id = \"11\" name=\"Tim\" ...]", "11", "Timothy", "Andrew") 
           // output: "[customer id=\"11\" name=\"Tim\" ...]"

For the first one, use a lookahead assertion

   $"id\\s*=\\s*\"{id}\"(?!.*?name\\s*=)",
   $"id=\"{id}\" name=\"{name}\" ",

For the second one, use a capture group

   $"id\\s*=\\s*\"{id}\"(.*?)name\\s*=\\s*\"{oldName}\"",
   $"id=\"{id}\"$1name=\"{newName}\"",

Check these strings look like a regex when constructed.

Also, be aware that \\s will span newlines
(use [^\\S\\r\\n] to avoid that)

and .*? won't span newlines ( use a dot-all modifier if you need it to).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM