正则表达式替换包含一个字符串,并且不包含另一个子
问题描述:
我有一个看起来像这样的文本字符串:我如果没有指定名称是应该添加名称条目的功能正则表达式替换包含一个字符串,并且不包含另一个子
[customer id = "1" name="Bob" ...]
[customer id="2" name="Adam" ...]
[customer id="3" ...]
[customer id = "4" name="Julia" ...]
:
string AddNameIfDoesNotSpecified(string text, string id, string name)
{
return Regex.Replace(text,
$"id\\s*=\\s*\"{id}\"",
$"id=\"{id}\" name=\"{name}\"",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
}
这个工作原理除了即使有指定的名称它也会替换。如何更改正则表达式以检查子字符串是否存在"name\\s*="
,如果存在 - 不要替换?
,我需要实现的另一件事是UpdatName方法:
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);
}
它的工作原理,但如果我们有id
和name
之间等其他属性:
[customer id="5" gender="female" name="Marta" ...]
它不会工作,我如何使用正则表达式在C#中工作?我应该使用组吗?
例子:
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\" ...]"
答
- 如何修改我正则表达式来检查是否有 “名\ S * =” 字符串,如果它的存在 - 不做更换?
你可以简单地检查一个空的name属性如下:
Regex.Replace(text,
$"id\\s*=\\s*\"{id}\"\\s+name\\s*=\\s*\"\"",
$"id=\"{id}\" name=\"{name}\"",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
但是,如果有如图所示here之间的其他属性,这是行不通的。
开始=“2”>
- 如果我们有ID和名之间其他属性..它是行不通的。我应该使用组吗?
是,这个想法是捕捉你的属性之间的文本,然后再次使用它的组号(在我的模式$ 2)添加ID:
Regex.Replace(text,
$"(id\\s *=\\s *\"{id}\")(.*?)(name\\s*=\\s*\"{oldName}\")",
$"id=\"{id}\"$2name=\"{newName}\"",
RegexOptions.IgnoreCase | RegexOptions.Compiled)
这同样适用于第一图案:
$"id\\s*=\\s*\"{id}\"(.*?)name\\s*=\\s*\"\"",
$"id=\"{id}\"$1name=\"{name}\"",
虽然这个工程可能值得探索使用某种文档对象模型/ XML更加灵活。
答
对于第一个,使用前向断言
$"id\\s*=\\s*\"{id}\"(?!.*?name\\s*=)",
$"id=\"{id}\" name=\"{name}\" ",
对于第二个,使用捕获组
$"id\\s*=\\s*\"{id}\"(.*?)name\\s*=\\s*\"{oldName}\"",
$"id=\"{id}\"$1name=\"{newName}\"",
检查创建时这些字符串看起来像一个正则表达式。
而且,要知道,\s
将跨越换行符
(使用[^\S\r\n]
避免)
和.*?
不会跨越换行符(如果你需要它使用一个点的所有修改)。
_有些人遇到问题时会想:“我知道,我会用正则表达式。”现在他们有两个问题_;) – Fabio
你有一些数据(键值对)串行化为一个字符串行。 1.反序列化它以键入您的语言理解。2.通过语言编译器提供的好处以简单的方式操作数据。 3.回到格式化的字符串行。很明显,你应该有这种代表你的数据的类,因为你的应用程序以某种方式使用它... – Fabio