正则表达式.取代怪异的行为

本文关键字:取代 正则表达式 | 更新日期: 2023-09-27 18:17:39

我有一系列需要去标记化的字符串。字符串来自数据库,看起来像这样

Subject: Ticket ##TicketID## Created
ShortText: Ticket ##TicketName## created (ID: ##TicketID##).
LongText: <a href="##BaseUrl##/Ticket/Details/##TicketID##">##TicketName##</a> was created on ##CreatedOn##.

每个令牌是关联事件对象的属性名,基于某些操作触发。例如,TicketCreatedEvent对象可能看起来像

public class TicketCreatedEvent : ILAMPEvent {
    public Guid TicketID { get; set; }
    public string TicketName { get; set; }
    public DateTime CreatedOn { get; set; }
    public string BaseUrl { get; set; }
}

我能够找到/弄清楚事情,只要动态地创建一个基于对象的字典,映射属性名称到值。我在正则表达式上也取得了一些进展。取代电话。使用

替换Subject字符串中的标记效果很好:
Regex.Replace(templates.Subject, @"##(.*)##", match => map[match.Groups[1].Value]);

然而,它在短文本或长文本上工作得不是很好。从抛出的异常中我可以看出,Regex匹配太多了。而不是匹配

##TicketName## 
从字符串中找到

,它试图匹配

##TicketName## created (ID: ##TicketID##

显然我想分别匹配这些标记。我认为这是我的错误,但我错过了什么?

正则表达式.取代怪异的行为

.*是贪婪的,并尽可能匹配,包括中间的## s。

你有三个选择:

  1. 使用延迟量词:@"##(.*?)##"。工作原理相同,但现在.*?将匹配尽可能少的字符。这在大多数情况下应该没问题。
  2. 指定不允许# s在## s和@"##([^#]*)##"之间。然而,这意味着##hello#there##不匹配。
  3. 更具体地说,不允许## s在## s和@"##((?:(?!##).)*)##"之间。这允许##hello#there##。对于当前的应用程序来说,这可能是多余的,但它将有助于更复杂的情况,例如处理嵌套结构。