这个正则要怎么写呢?一个不标准的 json 字符串,想要手动给他修改正确

2022-07-24 12:49:12 +08:00
 morri

已经完成了键的修改,没把加""的都加上了, 但值要如何正则给加上""呢?

func TestMakeToJsonStr(t *testing.T) {
	str := `{label  :用户 id,searchType:1,hide:1,disabled:1,required:1,options:1:yes:tag-info,2:no:tag-danger}`
	// 替换所有空格
	// 处理 key 未加""的内容字段
	replace, _ := gregex.Replace(`\s`, []byte(""), []byte(str))
	replace, _ = gregex.Replace(`label|"label"`, []byte(`"label"`), replace)
	replace, _ = gregex.Replace(`fieldType|"fieldType"`, []byte(`"fieldType"`), replace)
	replace, _ = gregex.Replace(`searchType|"searchType"`, []byte(`"searchType"`), replace)
	replace, _ = gregex.Replace(`editHide|"editHide"`, []byte(`"editHide"`), replace)
	replace, _ = gregex.Replace(`addHide|"addHide"`, []byte(`"addHide"`), replace)
	replace, _ = gregex.Replace(`hide|"hide"`, []byte(`"hide"`), replace)
	replace, _ = gregex.Replace(`disabled|"disabled"`, []byte(`"disabled"`), replace)
	replace, _ = gregex.Replace(`required|"required"`, []byte(`"required"`), replace)
	replace, _ = gregex.Replace(`comment|"comment"`, []byte(`"comment"`), replace)
	replace, _ = gregex.Replace(`options|"options"`, []byte(`"options"`), replace)
	// 处理值未加个""的字段
	fmt.Println(string(replace))
}

现在的执行结果

{"label":用户 id,"searchType":1,"hide":1,"disabled":1,"required":1,"options":1:yes:tag-info,2:no:tag-danger}

注明 键就是那几个是固定的

2986 次点击
所在节点    程序员
35 条回复
sutra
2022-07-24 14:50:49 +08:00
Go's stdlib regexp engine is RE2 which does not support lookaround (e.g. the ?! negative lookahead operator).

难啊。
sutra
2022-07-24 16:20:05 +08:00
sutra
2022-07-24 16:43:15 +08:00
搞个第三方库,支持 ?! 就行了。
sutra
2022-07-24 16:44:12 +08:00
使用 regexp2 的 go 版本见上面 Java 版本后面的回复,v2ex 不让我贴太多 URL 。
wxf666
2022-07-24 16:44:29 +08:00
#1 说这是 golang ?在 regex101 看了下,支持的正则特性有点少。。

反正不要求通用方案,那就随便写咯


『模式匹配』

\s*"?(options)"?\s*:\s*"?(.*?)"?\s*(})|\s*"?(\w+)"?\s*:\s*"?(.*?)"?\s*(,)


『全部替换为』

\"$1$4\":\"$2$5\"$3$6


『要求』

1. 除了 options 外,其他键的值不包含『,』(锚定键值对结束)

2. options 键在最后一位,其值不包含『}』(锚定键值对结束)

3. 头尾裹上『"』后(若已有则不裹)仍符合 json 字符串规范

 (如:『 key: 他说"xxx",我不以为然』变成『"key": "他说"xxx",我不以为然"』会出问题)


『例子』

原文:

{
  "label" : 用户 id ,
   searchType : "1" ,
  "hide" : 1 ,
   disabled : "1" ,
  "required" : "1" ,
   options:1:yes:tag-info,2:no:tag-danger
}

替换后:

{"label":"用户 id","searchType":"1","hide":"1","disabled":"1","required":"1","options":"1:yes:tag-info,2:no:tag-danger"}
morri
2022-07-24 17:13:18 +08:00
@sutra
@wxf666 谢谢 我后面改改

现在这样写的

```
func makeToJsonStr(str string) string {
// 替换所有空格
replace, _ := gregex.Replace(`\s`, []byte(""), []byte(str))
// 处理 key 未加""的内容字段
replace, _ = gregex.Replace(`label|"label"`, []byte(`"label"`), replace)
replace, _ = gregex.Replace(`fieldType|"fieldType"`, []byte(`"fieldType"`), replace)
replace, _ = gregex.Replace(`searchType|"searchType"`, []byte(`"searchType"`), replace)
replace, _ = gregex.Replace(`editHide|"editHide"`, []byte(`"editHide"`), replace)
replace, _ = gregex.Replace(`addHide|"addHide"`, []byte(`"addHide"`), replace)
replace, _ = gregex.Replace(`hide|"hide"`, []byte(`"hide"`), replace)
replace, _ = gregex.Replace(`disabled|"disabled"`, []byte(`"disabled"`), replace)
replace, _ = gregex.Replace(`required|"required"`, []byte(`"required"`), replace)
replace, _ = gregex.Replace(`comment|"comment"`, []byte(`"comment"`), replace)
replace, _ = gregex.Replace(`options|"options"`, []byte(`"options"`), replace)
// 处理值未加个""的字段
doAdd := func(temp string) []string {
defer func() {
if r := recover(); r != nil {
panic(r)
}
}()
strs := make([]string, 0)
for _, i := range gstr.Split(temp, ",") {
i = gstr.TrimAll(i)
if i == "" {
continue
}
begin := gstr.Split(i, ":")[0]
end := gstr.Split(i, ":")[1]
end = gstr.Replace(end, `"`, "")
strs = append(strs, fmt.Sprintf(`%s:"%s"`, begin, end))
}
return strs
}
temp := string(replace)
temp = temp[1 : len(temp)-1]
strs := make([]string, 0)
if !gstr.Contains(temp, `"options":`) {
strs = append(strs, doAdd(temp)...)
} else {
t := gstr.Split(temp, `"options":`)
strs = append(strs, doAdd(t[0])...)
t[1] = gstr.Replace(t[1], `"`, "")
t[1] = fmt.Sprintf(`"%s"`, t[1])
strs = append(strs, fmt.Sprintf(`"options":%s`, t[1]))
}
return fmt.Sprintf(`{%s}`, strings.Join(strs, ","))
}

```
wxf666
2022-07-24 17:35:03 +08:00
@morri 临时学了下 golang ,看起来运行没问题

『源码』

package main

import (
  "fmt"
  "regexp"
)

func main() {
   str := `{
    "label" : {label} ,
     searchType : "hide_222" ,
    "hide" : 333 disabled ,
     disabled : "required" ,
    "required" : "options" ,
     options:1:yes:tag-info,2:no:tag-danger
  }`
   re := regexp.MustCompile(`\s*"?(options)"?\s*:\s*"?(.*?)"?\s*(})|\s*"?(\w+)"?\s*:\s*"?(.*?)"?\s*(,)`)
   fmt.Println(re.ReplaceAllString(str, `"$1$4":"$2$5"$3$6`))
}


『输出』

{"label":"{label}","searchType":"hide_222","hide":"333 disabled","disabled":"required","required":"options","options":"1:yes:tag-info,2:no:tag-danger"}
morri
2022-07-24 19:08:01 +08:00
@wxf666 厉害上天~
morri
2022-07-24 19:22:33 +08:00
@wxf666 键是固定的几个,但是位置可以随意变化的,因为都是可选。
wxf666
2022-07-24 19:27:41 +08:00
@morri 那你要给出各字段值的特点才行啊

否则产生的歧义,怕是连人工都分不清:

{options:1:yes:tag-info,2:no:tag-danger,label:用户 id,searchType:1,hide:1,disabled:1,required:1}

也可以认为是:

{"options": "1:yes:tag-info,2:no:tag-danger,label:用户 id,searchType:1,hide:1,disabled:1,required:1"}
morri
2022-07-24 19:36:54 +08:00
@wxf666
最特别的值就是 `options:"1:yes:tag-info,2:no:tag-danger"`
因为这个 key 如果有出现那么它的值格式是这样的`value1:label1:class1,value2,label2,class2...` 如果是在不好判断,就让 `options` 的值必须带 “” 双引号吧。让程序单独判断一下..
wxf666
2022-07-24 20:16:34 +08:00
@morri 你试试这个:

\s*"?(options)"?\s*:\s*"?((?:[^,]*?:[^,]*?:[^,]*?,?)*)"?\s*([,}])|\s*"?(\w+)"?\s*:\s*"?(.*?)"?\s*([,}])

『要求』

1. options 键的值,为若干个以『,』分隔的 value:label:class (每个字段都不包含『,』)

2. 其他键的值不包含『,』『}』

3. 头尾裹上『"』后(若已有则不裹)仍符合 json 字符串规范
morri
2022-07-24 21:03:42 +08:00
@wxf666 多谢,可以~
sutra
2022-07-24 22:35:13 +08:00
只要有了 ?! ,且 option 的值里不包含其它 key: 就行。
Kisesy
2022-07-24 22:49:46 +08:00
我也遇到了一些奇特的格式,比如键没有引号,但是值有单引号,还有一种键和值都是单引号的
各式各样的不规范编码
wxf666
2022-07-25 00:24:22 +08:00
@sutra 我看 regex101 说,golang 的正则不支持断言,条件子组也不支持。你这是用了第三方库是嘛

每匹配一个字前,都要看看后面的是否是一个关键字,我总觉得性能消耗会大一点

另外,我老怀疑你『?!:』写错了……
356693212
2022-07-25 00:58:33 +08:00
1. 抽取 `{` 和 `}` 中的值
2. `,` 分割 key 和 value
3. 头尾加 `"`
4. value 为 `{` .goto 1.
5. 值转为 json
sutra
2022-07-25 10:07:29 +08:00
@wxf666 对呀,用了第三方库 regexp2 ,我在 #1 就说了,标准库不支持嘛。
lmshl
2022-07-25 11:11:32 +08:00
如果这东西生成有规律,建议一步到位写 parser
sutra
2022-07-25 12:14:02 +08:00
@wxf666 我怀疑你怀疑得是对的。于是我修了一下。

var keys = "label|fieldType|searchType|editHide|addHide|hide|disabled|required|comment|options";

var regex = "(?<key>" + keys + ")\\s*:(?<value>(?:(?!(" + keys + "):).)*)(?<delimiter>[\\,\\}])";
var replacement = "\"${key}\":\"${value}\"${delimiter}";

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/868341

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX