使用捕获组

时间:2016-04-28 08:34:51

标签: javascript json regex

我有一个字符串化的JSON,如下所示:

...

"message":null,"elementId:["xyz1","l9ie","xyz1"]}}]}], "startIndex":"1", 
"transitionTime":"3","sourceId":"xyz1","isLocked":false,"autoplay":false
,"mutevideo":false,"loopvideo":false,"soundonhover":false,"videoCntrlVisibility":0,
...,"elementId:["dgff","xyz1","jkh90"]}}]}]

......它继续。

我需要处理的部分是elementId键的值。 (第一行中的第二个键和最后一个键)。

此密钥存在于JSON字符串的多个位置。此键的值是一个包含4个字符ID的数组。

我需要用新的ID替换其中一个。

这个想法的核心是:

var elemId = 'xyz1' // for instance
var regex = new RegExp(elemId, 'g');
var newString = jsonString.replace(regex, newRandomId);
jsonString = newString;

这种方法存在一些问题。正则表达式将匹配JSON中任何位置的id。我需要一个只在elementId数组中匹配的正则表达式;而在其他任何地方。

我正在尝试使用捕获组来匹配我需要的事件,但我无法破解它。我有:

/.*elementId":\[".*(xyz1).*"\]}}]/

但是这与阵列中'xyz1的第一次出现不匹配。

所以,首先,我需要一个可以匹配elementId中所有'xyz1'的正则表达式;但没有其他地方。如果有帮助,elementId结束后的方括号和大括号的序列在字符串中的任何位置都不会改变。

其次,即使我有一个有效的捕获组,string.replace也没有按预期行事。它不是仅仅取代捕获组内的匹配,而是取代整个匹配。

所以,我的第二个要求是只替换捕获的组,而不是整个匹配。

需要的是一段js代码,它将替换我需要的'xyz1并返回以下字符串(假设newRandomId是'abcd'):

"message":null,"elementId:["abcd","l9ie","abcd"]}}]}], "startIndex":"1", 
"transitionTime":"3","sourceId":"xyz1","isLocked":false,"autoplay":false
,"mutevideo":false,"loopvideo":false,"soundonhover":false,"videoCntrlVisibility":0,
...,"elementId:["dgff","abcd","jkh9"]}}]}]

请注意,'sourceId'的值不受影响。

编辑:我必须使用JSON。我不能解析它并使用该对象,因为我不知道旧id可能在对象中的所有位置并且多次循环(对于多个元素)将是耗时的

1 个答案:

答案 0 :(得分:1)

假设您不能只解析和更改JS对象,可以使用2个正则表达式:一个用于提取数组,另一个用于更改内部所需的ID:

var output = input.replace(/("elementId"\s*:\s*\[)((?:".{4}",?)*)(\])/g, function(_,start,content,end){
  return start + content.replace(/"xyz1"/g, '"rand"') + end;
});

参数_startcontentend是由正则表达式(documentation here)生成的:

  • _是完整匹配的字符串(从"elementId:\[])。我选择这个名字,因为它是你不使用的参数的旧约定
  • start是第一组("elementId:\[
  • content是第二个捕获的组,即数组的内部部分
  • end ID为第三组]

使用组而不是硬编码返回的字符串中的startend部分有两个目的

  • 避免重复(DRY原则)
  • 可以使用变量字符串(例如在我的正则表达式中我接受:之后的可选空格)

var input = document.getElementById("input").innerHTML.trim();
var output = input.replace(/("elementId":\s*\[)((?:".{4}",?)*)(\])/g, function(_,start,content,end){
  return start + content.replace(/"xyz1"/g, '"rand"') + end;
});

document.getElementById("output").innerHTML = output;
Input:
<pre id=input>
"message":null,"elementId":["xyz1","l9ie","xyz1"]}}]}], "startIndex":"1", 
"transitionTime":"3","sourceId":"xyz1","isLocked":false,"autoplay":false
,"mutevideo":false,"loopvideo":false,"soundonhover":false,"videoCntrlVisibility":0,
...,"elementId":["dgff","xyz1","jkh9"]}}]}]
</pre>
Output:
<pre id=output>
</pre>

注意:

  • 如果不在一个数组中重复搜索到的id,那么在一个正则表达式中完成整个操作会很容易。但是目前的结构可以很容易地同时处理几个ID。
  • 我使用非捕获组(?:...)来整理传递给外部替换回调的参数