正则表达式:是否可以在捕获组内进行替换?

Regex: Is it possible to do a substitution within a capture group?

我有这一行JSON文本:

{"schemaText":{"fields":[{"name":"AX_SND_TYPE","type":"string"},{"name":"BWORK","type":"int"}],"name":"XXXSchema","type":"record"},"description":"Autogenerated by NiFi"}

可以看出有一个叫做"schemaText"的属性包含了一个对象,我想把它转换成一个字符串,所以我需要做的'only'事情是在 属性 的开头和结尾添加引号并转义里面的引号。

使用下面的正则表达式(并不是说我的正则表达式知识真的很低),我能够完成第一步:

({"schemaText":)(\{"fields":\[.*)(,"description.*)

使用替换

""

给出结果:

{"schemaText":"{"fields":[{"name":"AX_SND_TYPE","type":"string"},{"name":"BWORK","type":"int"}],"name":"XXXSchema","type":"record"}","description":"Autogenerated by NiFi"}

但仍然需要转义引号才能得到这个:

{"schemaText":"{\"fields\":[{\"name\":\"AX_SND_TYPE\",\"type\":\"string\"},{\"name\":\"BWORK\",\"type\":\"int\"}],"name":"XXXSchema","type":"record"}","description":"Autogenerated by NiFi"}

这是有效的 JSON 格式。

问题是:有没有办法在同一个正则表达式中转义 $2 捕获组内的引号?

提前致谢。

我建议使用代码解决这个问题,例如香草 JavaScript:

let json = '{"schemaText":{"fields":[{"name":"AX_SND_TYPE","type":"string"},{"name":"BWORK","type":"int"}],"name":"XXXSchema","type":"record"},"description":"Autogenerated by NiFi"}';

let obj = JSON.parse(json);
let schemaTextAsString = JSON.stringify(obj.schemaText)
obj.schemaText = schemaTextAsString

var result = JSON.stringify(obj)

你可以看到这个工作 here

请注意,在您想要的输出中,您没有转义 schemaText 的名称字段中的引号,但这段代码确实如此。

终于每次用到正则表达式的时候总会想起这篇经典文章"Regular Expressions: Now You Have Two Problems"!

你的问题的答案是否定的,这是不可能的。您实际上是在尝试在单个正则表达式中执行两个不同的、不相关的替换。这是一个正则表达式引擎不支持的功能。

想一想:您的第一个要求是让引擎对整个文本(引号)执行替换,然后,对于您的第二个要求,引擎必须以某种方式回溯并对文本执行更多替换可能已经更改,也可能没有更改:例如:它需要对已经替换的文本执行新的匹配,根据第一次替换的内容,该文本甚至可能不再存在!

如果像您所说的那样,您已经有了行之有效的方法,请保留它。单个正则表达式根本不适合您要执行的操作。

仅供参考,您实际上可以 匹配 在每个应该发生替换的位置,使用如下表达式:

/({"schemaText":)|}(,"description")(.*)|([^"]*)"/g

正如其他人所提到的,唯一的问题是您想要做的不仅仅是匹配;你想执行 "conditional replacement" 因为不存在一个单一的包罗万象的替换来覆盖你正在处理的所有 3 个案例(插入开始 ",在引号前插入 \,并插入结尾 ")。

实际上,您只需调用一次 replace() 即可完成此操作:

var test = "{\"schemaText\":{\"fields\":[{\"name\":\"AX_SND_TYPE\",\"type\":\"string\"},{\"name\":\"BWORK\",\"type\":\"int\"}],\"name\":\"XXXSchema\",\"type\":\"record\"},\"description\":\"Autogenerated by NiFi\"}";
window.alert(test.replace(/({"schemaText":)|}(,"description")(.*)|([^"]*)"/g, function(a,b,c,d,e){ return (b=="{\"schemaText\":"?b+"\"":(c==",\"description\""?"}\""+c+d:e+"\\"")) })));

所以它在技术上是 "the same regex",但是替换参数使用内联函数作为替换而不是静态字符串。