使用捕获组查找和替换json字符串中出现的所有短语

Find and Replace all occurrences of a phrase in a json string using capturing groups

本文关键字:短语 字符串 json 查找 替换      更新时间:2023-09-26

我有一个字符串化的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替换其中一个ID。

这个想法的核心是:

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

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

我正试图使用一个捕获组来匹配我需要的事件,但我无法完全破解它。我有:

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

但这与数组中第一次出现的"xyz1"不匹配。

因此,首先,我需要一个regex,它可以匹配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可能在对象中的所有位置,并且多次循环(对于多个元素)将是耗时的

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

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

参数_startcontentend是正则表达式(此处为文档)的结果:

  • _是整个匹配字符串(从"elementId:'[])。我选择这个名字是因为它是你不使用的论点的旧惯例
  • start为第一组("elementId:'[
  • content是第二个被捕获的组,即阵列的内部
  • end标识第三组,]

使用组而不是对返回字符串中的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,那么在一个regex中完成整个操作将很容易。但是目前的结构使得同时处理多个要替换的id变得容易
  • 我使用未捕获的组(?:...)来整理传递给外部替换回调的参数