在c#中我正在寻找一个只匹配第一次出现的正则表达式

时间:2017-09-26 07:21:08

标签: c# regex

在下面的一段代码(C#)中,我想替换ContentType注释中的Order和GUID的值:

[ContentType(
    DisplayName = "My First Block",
    Order = 133536,
    GUID = "0f02e38a-a6e2-4333-9bd1-c61cf573d8d3",
    Description = "Just an example block.",
    GroupName = "Blocks.Content"
    )]
public class MyFirstBlock : BaseBlock
{
    [CultureSpecific]
    [Display(
        Name = "Title",
        Order = 100,
        Description = "The title",
        GroupName = "Information")]
     [Required]
     public virtual XhtmlString Title { get; set; }
}

我正在使用以下正则表达式来查找值: 订单:(?<=Order = )\d{4,}(?=[,)]) GUID:(?<=GUID = \").*(?=\")

这些工作但它们有一些缺点。对于Order regex,我希望不必寻找至少4位数。我宁愿做(?<=Order = )\d*(?=[,)])所以如果当前订单值小于4位或甚至根本没有输入,它也会找到正确的位置。但这也将匹配标题的显示注释中的顺序。我试过让表达不贪婪,就像我在搜索我的问题时找到的每一个搜索结果中所接受的答案一样,但这似乎没有做任何事情。

对于GUID,我遇到了同样的问题。我无法确定文档中是否会有其他GUID,我不想替换它。所以对于这个表达式问题基本相同,我只想在文档中找到第一个GUID的值。

我尝试过的另一种方法是在ContentType块中查找Order和GUID,但是我无法让它工作。

将这个问题置于上下文中的一些背景信息:我正在编写一个VS扩展,它将根据用户选择的文本生成订单号,并用新生成的GUID替换GUID。我正在使用EnvDTE.TextDocument.ReplacePattern()来替换生成后的订单和GUID的值。

1 个答案:

答案 0 :(得分:1)

您可以使用以下解决方案:

var result = Regex.Replace(
        Regex.Replace(input, @"(?s)(\[ContentType\((?:(?!\)]).)*?\bOrder\s*=\s*)\d*(.*?\)])", "${1}<<ORDER>>$2"),
        @"(?s)(\[ContentType\((?:(?!\)]).)*?\bGUID\s*=\s*""?)[\w-]*(.*?\)])", 
        "${1}<<GUID>>$2");

请参阅C# online demo,其中显示OrderGUID值仅在ContentType部分中替换:

Order = <<ORDER>>,
GUID = "<<GUID>>",

请注意,使用花括号可以明确替换反向引用,因为很可能您的替换将以数字开头,并且可能会创建无效的组引用。

模式匹配:

  • (?s) - 启用.以匹配换行符
  • (\[ContentType\((?:(?!\)]).)*?\bGUID\s*=\s*"?) - 第1组捕获:
    • \[ContentType\( - [ContentType(子字符串
    • (?:(?!\)]).)*? - 任何未启动)]序列的char,尽可能少,
    • \bGUID - 整个字GUID(或Order
    • \s*=\s* - 包含0 +空格的=
    • "? - 可选的"
  • [\w-]* - 0个或多个字词或-字符
  • (.*?\)]) - 第2组:尽可能少的字符,直至第一个)]包括它们。