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

问题描述 投票:2回答:3

我有这一行JSON文本:

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

可以看出,有一个名为“schemaText”的属性包含一个对象,我想将其转换为字符串,因此我需要做的“唯一”事情是在属性的开头和结尾添加引号并转义内部引用。

使用正则表达式(不是我的正则表达式知识真的很低),我能够做到第一步:

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

使用替换

$1"$2"$3

给出结果:

{"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捕获组内的引号?

提前致谢。

json regex avro confluent-schema-registry
3个回答
2
投票

你的问题的答案是否定的,这是不可能的。你真的想在一个正则表达式中做两个不同的,无关的替换。这是一个没有正则表达式引擎支持的功能。

想一想:你的第一个要求是引擎在整个文本(引号)上执行替换,然后,对于你的第二个要求,引擎必须以某种方式回溯并在文本上执行更多替换,这可能有也可能没有已经改变了:例如:它需要对已经替换的文本执行新的匹配,这取决于第一次替换所做的,甚至可能不再存在!

如果,正如你所说,你已经有一个有效的方法,那就保持这种状态。单个正则表达式根本不适合您要执行的操作。


1
投票

我建议使用代码解决此问题,例如与香草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"


1
投票

只是为了您的信息,您实际上可以在每个应该发生替换的位置匹配,使用如下表达式:

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

正如其他人所提到的,唯一的问题是你想做的不仅仅是匹配;你想执行一个“条件替换”,因为不存在一个全部替换,它将涵盖你正在处理的所有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+"\\\"")) })));

所以它在技术上是“相同的正则表达式”,但替换参数使用内联函数作为替换而不是静态字符串。

© www.soinside.com 2019 - 2024. All rights reserved.