2

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

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; }
}

就基于对象动态创建字典,将属性名称映射到值而言,我能够找到/弄清楚事情。我还能够在 Regex.Replace 调用上取得一些进展。使用以下方法替换主题字符串中的标记非常有用:

Regex.Replace(templates.Subject, @"##(.*)##", match => map[match.Groups[1].Value]);

但是,它在 ShortText 或 LongText 上效果不佳。从抛出的异常中我可以看出,正则表达式匹配太多。而不是匹配

##TicketName## 

从字符串中,它试图匹配

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

显然,我想单独匹配每个令牌。我认为这是我的错误,但我错过了什么?

4

1 回答 1

9

.*是贪婪的并且尽可能多地匹配,包括干预##s.

你有三个选择:

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

使用其中任何一个最清楚地传达您的意图。

于 2013-06-07T19:30:31.873 回答