2014-11-05 87 views
4

我试图提高我对正则表达式的理解,但这个有我很神秘。 我开始与定义为一些文字:正则表达式替换JSON是从数组中删除一个对象

var txt = "{\"columns\":[{\"text\":\"A\",\"value\":80},{\"text\":\"B\",\"renderer\":\"gbpFormat\",\"value\":80},{\"text\":\"C\",\"value\":80}]}"; 

,并做了替换如下:

txt.replace(/\"renderer\"\:(.*)(?:,)/g,"\"renderer\"\:gbpFormat\,"); 

导致:

"{"columns":[{"text":"A","value":80},{"text":"B","renderer":gbpFormat,"value":80}]}" 

我所期待的是为renderer属性值删除引号;发生了哪些事情,也是C这一列完全没有了!我真的很喜欢有人解释我的Regex如何删除列C

作为一个额外的好处,如果你可以解释如何删除renderer任何值附近的引号(即,所以我不必在正则表达式中硬编码值gbpFormat),这将是太棒了。

+0

'txt'从哪里来?它可能会被打破JSON,我会尝试修复它的源头。然后你可以解析它并使用JavaScript语法改变属性。 – elclanrs 2014-11-05 23:51:26

+0

这是因为你正在使用一个贪婪的操作符,使用'\“渲染器\”(:。*?)(?:,)将它改变为一个懒惰的操作符' – 2014-11-05 23:53:25

回答

0

尝试这样的:

txt = txt.replace(/"renderer":"(.*?)"/g,'"renderer":$1'); 

在您使用表达的问题是这一部分:

(.*)(?:,) 

默认情况下,*量词是贪婪默认情况下,这意味着它会尽可能地吞噬,所以它会跑到你的字符串中的最后一个逗号。最简单的解决办法是把在一个非贪婪量词,由星号后加一个问号,改变你表达的部分看起来像这样

(.*?)(?:,) 

因为我在提出的解决方案这个答案的顶部,我也删除了与逗号相匹配的部分,因为我认为只需在引号之间匹配所有内容就简单了。至于你的奖金问题,为了替换匹配的值而不是硬编码gbpFormat,我使用了反向引用($1),它将第一个匹配的组插入到替换字符串中。

2

您正在使用贪婪运营商,而您需要懒惰之一。更改此:

"renderer":(.*)(?:,) 
       ^---- add here the '?' to make it lazy 

"renderer":(.*?)(?:,) 

Working demo

enter image description here

你的代码应该是:

txt.replace(/\"renderer\"\:(.*?)(?:,)/g,"\"renderer\"\:gbpFormat\,"); 

如果你正在学习正则表达式,那么看看这个documentation来更多地了解贪婪。一个很好的提取知道这是:

小心贪婪

假设您想使用正则表达式来匹配HTML标记。你知道 输入将是一个有效的HTML文件,所以正则表达式不需要排除任何无效使用尖括号。如果它位于尖括号之间的 ,它是一个HTML标记。

大多数刚接触正则表达式的人都会尝试使用<。他们 会感到惊讶,当他们在一个字符串上测试它,这是一个 第一测试。您可能预期正则表达式匹配,并且当匹配后 继续时,

但它没有。正则表达式将匹配第一个。显然不是 我们想要的。原因是加号是贪婪的。也就是说, plus会导致正则表达式引擎重复执行前一个令牌,但可能的情况是 。只有当这导致整个正则表达式失败时,正则表达式 引擎才会回溯。也就是说,它会回到加号,让它在上一次迭代中给出 ,并继续处理剩余的正则表达式。

像加号一样,明星和使用大括号的重复是 贪婪。

0

不要使用正则表达式操纵JSON。就像你发现的那样,你很可能会打破它,更重要的是没有必要。

此外,一旦你已经改变

'{"columns": [..."renderer": "gbpFormat", ...]}' 

'{"columns": [..."renderer": gbpFormat, ...]}'  // remove quotes from gbpFormat 

然后这不再是有效的JSON。 (JSON要求属性值是数字,带引号的字符串,对象或数组。)因此,您将无法解析它,或将它发送到任何地方并使其正确解释。

因此,你应该分析它与启动,然后操纵所产生的实际JS对象:

var object = JSON.parse(txt); 
object.columns.forEach(function(column) { 
    column.renderer = ghpFormat; 
}); 

如果你想更换renderer属性与价值本身的任何引用值,那么你可以尝试

column.renderer = window[column.renderer]; 

假设该值在全局名称空间中可用。

这个问题属于“我需要一个正则表达式,或者我写了一个,它不工作,我不知道为什么它必须是一个正则表达式,但我听说他们可以做各种事情,所以这正是我想象的我必须需要的。“人们使用正则表达式来尝试执行太多复杂的匹配,分割,扫描,替换和验证任务,包括诸如HTML之类的复杂语言,或者在这种情况下使用JSON。几乎总是有一个更好的方法。

我能想象的唯一一次想用正则表达式来操纵JSON的原因是,如果JSON以某种方式破坏了,或许是由于服务器代码中的一个错误,并且它需要被修复才能被解析。

+0

这很有趣;每次我问一个问题以了解更多关于正则表达式的问题时,人们都会说'不要使用正则表达式“。那么猜猜怎么样?正则表达式存在于很多地方,可以非常有用,我想学习它。所以不,我的问题不属于你提到的范畴。 – Black 2014-11-06 23:08:31

+0

@Francis:当然,但你应该想出更实际的使用正则表达式的有用方法,而不是解析HTML。请记住,SO不只是一个问答网站,而是为未来几代程序员提供知识库。我们不想让他们留下不良做法的例子。由于人们也在搜索和搜索问题,也可以通过谷歌搜索问题,最好给出问题的好题目,以帮助他们找到他们想要的东西。在这种情况下,相关问题不是“正则表达式正在移除对象”,而是“正则表达式正在取代太多”。 – 2014-11-07 02:35:50