非固定长度的lookbehind解决方法

Posted

技术标签:

【中文标题】非固定长度的lookbehind解决方法【英文标题】:Non-fixed length lookbehind workaround 【发布时间】:2017-11-30 01:43:33 【问题描述】:

考虑以下 JSON: 第一个:


  "Good": 
    "a": "<good>",
    "c": "<better>",
    "e": "<best>"
  ,
  "Bad": 
    "a": "<bad>",
    "c": "<worse>",
    "e": "<worst>"
  

第二个:


  "Good": 
    "a": "<kind of good>",
    "c": "<more good>",
    "e": "<the most good>"
  ,
  "Bad": 
    "a": "<a little bad>",
    "c": "<more bad>",
    "e": "<the most bad>"
  

第三:


  "Good": 
    "a": "<good>",
    "c": "<better>",
    "e": "<best>"
  ,
  "Bad": 
    "a": "<bad>",
    "c": "<better>",
    "e": "<worst>"
  

在所有情况下,我都必须从对象“Good”中提取属性“c”及其值,对值进行一些操作,然后用新值替换旧值。

问题出在对象“Bad”中。我对该对象的值不感兴趣,我不应该在那里替换任何东西。 到目前为止,我想出了那个正则表达式:

(?<!Bad)"c": "(<.*?>)"

明显的问题是对象“Bad”的名称不会立即出现在属性“c”之前,并且可能(和将)之间的符号不同。而且,据我所知,lookbehind 应该是固定长度,所以我不能只使用这样的东西:

(?<!Bad.*)"c": "(<.*?>)"

我在 C# 中使用正则表达式,所以我想只取第一次出现,但这不是最可靠的解决方案,它仍然无法解决替换问题。

谈论替换。我想过动态创建正则表达式以确保只替换正确的出现。但是对于第三个示例,该技巧不起作用,因为"c": "(&lt;better&gt;)" 将匹配对象“Good”和“Bad”。

谁能帮帮我?

【问题讨论】:

为什么要使用正则表达式而不是 JSON 解析器,例如 json.net、datacontractjsonserialize 或 javascriptserializer? @dbc 嗯,这是一个很好的问题。一切开始很简单,然后变成了这个怪物;可能,我真的不需要用正则表达式解析它。不过,如果有使用正则表达式的正确方法,我很乐意知道。 如果不平衡表达式,您将无法使用 .NET 正则表达式解析 JSON,与使用实际的 JSON 解析器相比,这需要付出很多努力。 谢谢,@Ryan,我想我必须这样做。 【参考方案1】:

您可以使用 JSON.NET 来解析 JSON。既然知道JSON中有一定的值,就可以用一个简单的代码(这里只是把e的值用括号括起来):

dynamic parsedObject = Newtonsoft.Json.JsonConvert.DeserializeObject(data);
parsedObject["Good"]["e"] = $"(parsedObject["Good"]["e"])";
var res = parsedObject.ToString();

【讨论】:

是的,这似乎是我要使用的方向。谢谢你,维克托!

以上是关于非固定长度的lookbehind解决方法的主要内容,如果未能解决你的问题,请参考以下文章

Hash冲突的解决方法

如何做一个perl可变长度正面lookbehind或类似的东西[复制]

如何使用分而治之的方法解决“固定大小的最大子数组”?

Luncene介绍

正则表达式的可变长度lookbehind-assertion替代方案

listview添加长度不固定分割线