求教下疑惑了很久的一个正则

2021-06-30 16:01:07 +08:00
 Jwyt
比如一个类似 json 的字符串
"date":["2020-06-03","2020-06-05","2020-06-12","2020-06-19","2020-06-24","2020-07-03","2020-07-10","2020-07-17","2020-07-24","2020-07-31","2020-08-07","2020-08-14","2020-08-21","2020-08-28","2020-09-04","2020-09-11","2020-09-18","2020-09-25","2020-10-09","2020-10-16","2020-10-23","2020-10-30","2020-11-06","2020-11-13","2020-11-20","2020-11-27","2020-12-04","2020-12-11"],"data":[0,-0.33,-0.04,-0.33,-0.32,-0.18,-0.99,-0.84,-0.33,-0.57,-0.65,-0.52,-0.65,-0.95,-1.08,-1.01,-0.96,-0.89,-0.97,-0.98,-0.71,-0.6,-0.47,-0.63,-0.79,-0.59,-0.41,-0.33],"ret":[0,0,0.02,1.33,1.27,1.53,1.33,1.54,1.8,1.96,2.16,2.3,2.34,2.31,2.38,2.41,1.89,2.01,2.18,2.29,2.39,2.49,2.6,2.6,2.51,2.54,2.71,2.86]

求教能否只用一条正则获取"ret": 里面的所有数值(多行)?
结果:
0
0
0.02
1.33
....
1370 次点击
所在节点    正则表达式
14 条回复
keepeye
2021-06-30 16:15:09 +08:00
可能匹配不出来,只能把 ret 取出来 split
IgniteWhite
2021-06-30 16:19:40 +08:00
同不会写。我的感觉是这种 pattern 是非正则的,如果让我去做我会把 ret 里的内容用正则提出来,再用一个 csv parser 或者一个正则包里的 split 函数得到数值
woodensail
2021-06-30 16:23:00 +08:00
一次正则理论上可以,不过要用断言判断当前数字后面没有 ret 出现,而且老实说通用性不强,所以我倾向于两次正则
str.match(/ret[^[]+\[([^[]+)\]/)[1].match(/[\d\.]+/g)
InDom
2021-06-30 16:27:20 +08:00
正则不是万能的,另外不要写过于复杂的正则,这玩意写不好性能非常差!!!

非要凑在一个里面实现,可能代码量少了,但执行时间会 toooooooooooo looooooooooog
woodensail
2021-06-30 16:29:32 +08:00
更正一下,第一个正则里面匹配数字内容的部分应该改成排除右括号。虽然左括号也没错,但是确实右括号更合理。

str.match(/ret[^[]+\[([^\]]+)/)[1].match(/[\d\.]+/g)
keepeye
2021-06-30 16:33:28 +08:00
@woodensail 能一次匹配出结果吗 我想学习下
imn1
2021-06-30 16:35:31 +08:00
这个正则不难,问题的点不在这里,而是正则输出的是 str 类型,而 json 表示的是 int 类型,除非只是显示用途,不然还有一个转换步骤,那还不如直接 json 解
莫不是一个 GB 级的 json ?
woodensail
2021-06-30 16:40:03 +08:00
@keepeye str.match(/[\d\.]+(?!.*ret)/g)
用零宽断言,匹配数字同时要求数字后面不会出现 ret 字符.
缺点 1: 性能相比两次法差了很多。
缺点 2: 如果字段顺序变了或者 ret 字段后面又追加了其他字段就不行了。
lujjjh
2021-06-30 16:53:44 +08:00
str.match(/(?<="ret":\[[^\]]*)[^,\]]+/g)

抛开 lookbehind assertion 的兼容性问题,这么写也是不够准确的,要看你这个“类似 json 的字符串”具体格式是什么样
keepeye
2021-06-30 17:05:27 +08:00
@woodensail 是的,实际情况可不能保证说 ret 是最后一个字段,map 是没有顺序的
Jwyt
2021-06-30 17:06:46 +08:00
@keepeye @IgniteWhite @InDom
谢谢,看来还是上代码
@imn1 也不是- - 就是一个老爬虫框架,使用有些限制
Jwyt
2021-06-30 17:09:37 +08:00
@woodensail 是的,ret 后面的内容我没复制,不过 ret 里的内容确实匹配到了
Jwyt
2021-06-30 17:20:57 +08:00
@lujjjh 感谢 确实可以。不过就像你说的,刚好这个老框架(php)不兼容模糊长度的断言。。看来还是得用其他办法了
wjfz
2021-06-30 18:21:22 +08:00
给两头各加一个花括号,然后 json decode

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

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

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

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

© 2021 V2EX