将字符替换为另一个字符,除非它位于大括号之间

时间:2013-11-26 06:58:10

标签: regex

我想用以下字符串做的是用制表替换所有的“comas”,除非所说的昏迷在大括号{}之间。

说我有:

goldRigged,1,0,0,0,1,0,0,0,1,"{"LootItemID": "goldOre", "Amount": 1}"

结果应为:

goldRigged\t1\t0\t0\t0\t1\t0\t0\t0\t1\t"{"LootItemID": "goldOre"**,** "Amount": 1}"

我已经\"(\\{((.*?))\\})\"允许我匹配{ }之间的内容。 我们的想法是用某些内容排除内容,并使用类似\",^(\\{((.*?))\\})\"之类的内容匹配任何内容。 但我想通过这样做会排除逗号本身。

6 个答案:

答案 0 :(得分:1)

你需要的是一种负向前瞻和负面的后视。但是,这将构成一个非常复杂的陈述:

匹配所有前面没有开括号的逗号,只要它们之前没有前面的括号(加上逗号右侧的恢复逻辑)。这将导致表达式难以处理,因为正则表达式引擎不断需要从当前位置向上和向下运行字符串,效率相当低。

相反,迭代字符串的所有字符。如果匹配左大括号,请设置转义提示。当你找到一个闭合支撑时,将其移除。当您找到逗号时,请在未设置转义提示时替换它。将结果写入某种字符串缓冲区,您的解决方案将比正则表达式更有效率。

答案 1 :(得分:1)

您希望使用否定的外观来实现此目的:

(?<![\{\}]),*(?![\{\}])应该有效,请点击此处:http://regex101.com/r/gG3oU1

答案 2 :(得分:1)

在正则表达式中使用否定前瞻(?!expr)和否定后瞻(?<!expr) 例如,您可以像这样编码:

System.Text.RegularExpressions.Regex.Replace(
"goldRigged,1,0,0,0,1,0,0,0,1, {\"LootItemID\": \"goldOre\", \"Amount\": 1}" ,
@"(?<!\{[^\}].*)[,](?![^\{]*\})", "\t");

答案 3 :(得分:0)

您的输入行是否包含{仅在最后一个令牌中? 如果是,那么你可以尝试这种蛮力方法

echo "goldRigged,1,0,0,0,1,0,0,0,1,"{"LootItemID": "goldOre", "Amount": 1}"" | awk -F'{' '{one=$1;gsub(",","\t",one);printf("%s{%s\n",one,$2);}

答案 4 :(得分:0)

以下正则表达式是一种昂贵的方式。根据@Sniffer的建议,解析器在这里会更好:)

(?=,.*?"{),|(?!,.*?\}),

第一次轮换

(?=,.*?"{), - 确保逗号位于序列"{

之外

第二次轮换

(?!,.*?\}), - 确保逗号不在序列}"

将会有一些尚未考虑的边缘情况,即解析器进入

答案 5 :(得分:0)

我认为你实际上只需要一个前瞻:

,(?=[^{}]*({|$))

读取:逗号,然后是一些非括号,然后是一个开括号或结束。

JS中的示例:

> x = 'goldRigged,1,0,0,0,1,0,0,0,1,"{"LootItemID": "goldOre", "Amount": 1}",some,more{stuff,ff}end'
> x.replace(/,(?=[^{}]*({|$))/g, "@")
"goldRigged@1@0@0@0@1@0@0@0@1@"{"LootItemID": "goldOre", "Amount": 1}"@some@more{stuff,ff}end"

注意如果可以嵌套大括号,这不起作用,在这种情况下,您需要一个带递归(?R)的正则表达式引擎或正确的解析器。