python - 在 Python 中使用正则表达式匹配 JSON 键

标签 python json regex

我试图找到一个正则表达式来匹配嵌套 JSON 字符串表示的不同级别上的重复键。到目前为止,我所有的“解决方案”都遭受了灾难性的回溯。

该 JSON 字符串的示例如下所示:

d = {               
        "a": {      
            "b": {
                "c": {
                    "d": "v1", 
                    "key": "v2"
                }
            },
            "c": {  
                "g": "v3",     
                "key": "v4"
            },
            "key": "v5"        
        }
    }

key 的值就是目标。我的应用程序确实具有指向该键的所有对象名称。使用这些名称,我可以使用 for 循环来构建我的最终正则表达式。所以基本上我需要把零件放在中间。

例子: 如果我得到 "a""key",我可以构造以下内容:"a"[^}]*"key"。这与我的字符串 d 中的第一个“key”相匹配,它的值为 v2。

不过,应该发生的是 "a" + "key" 匹配值为 v5 的键。当完整路径 "a" + "b" + "c" + "key 时,值为 v2 的键应该匹配" 进来了。这个例子中的最后一个例子是在 "a" + "c" + "key 时匹配键和值 v4 " 已给出。

所以最后一个的完整正则表达式看起来类似于:

"a"MATCH_EVERYTHING_IN_BETWEEN_REGEX"c"MATCH_EVERYTHING_IN_BETWEEN_REGEX"key":\s*(\[[^}]*?\]|".*?"|\d+\.*\d*) 

明确地说,我正在寻找可以作为连接器插入的 MATCH_EVERYTHING_IN_BETWEEN_REGEX 表达式。这是为了确保它匹配我收到的路径的 key 。 JSON 字符串可以无限嵌套。

这是一个带有示例的在线正则表达式测试器: https://regex101.com/r/yNZ3wo/2

注意: 我知道这不是特定于 python 的,但我也很感谢在此上下文中的 python 提示。我考虑过构建自己的解析器,使用堆栈并计算 {} 但在此之前我想确保没有简单的正则表达式解决方案。

编辑: 我知道 json 库,但这并不能解决我的问题,因为我正在编辑器窗口内的字符串表示中跟踪我的目标坐标。我不是在寻找值本身,我可以从关联的字典中访问它们。

最佳答案

这很难。一个可能的解决方案是使用

  1. 用于匹配嵌套大括号的递归正则表达式*
    (?<="a": )({(?>[^{}]|(?1))*})
  2. 然后,继续使用垃圾桶方法在内部级别搜索键,即忽略整体匹配,只查看特定捕获组是否包含值
    (此处 $2,根据需要添加组):
    ({(?>[^{}]|(?1))*})|"key":\s*"([^"]*?)"

代码示例:

import regex as re

test_str = ("{                   \n"
    "  \"a\": {            \n"
    "    \"b\": {          \n"
    "      \"c\": {        \n"
    "        \"d\": \"v1\",  \n"
    "        \"key\": \"v2\" \n"
    "      }             \n"
    "    },              \n"
    "    \"c\": {          \n"
    "      \"g\": \"v3\",    \n"
    "      \"key\": \"v4\"   \n"
    "    },              \n"
    "    \"key\": \"v5\"  \n"
    "    }     \n"
    "  }                 \n"
    "}                   \n")

regex = r"(?<=\"a\": )({(?>[^{}]|(?1))*})"
innerRegex = r"({(?>[^{}]|(?1))*})|\"key\":\s*\"([^\"]*?)\""

matches = re.finditer(regex, test_str, re.DOTALL)

for n, match in enumerate(matches):
    n = n + 1    
    #print ("Match {n} was found at {start}-{end}: {match}".format(n = n, start = match.start(), end = match.end(), match = match.group()))
    inner = match.group()[1:-1]

    innerMatches = re.finditer(innerRegex, inner, re.DOTALL)
    for m, innerMatch in enumerate(innerMatches):
        #m = m + 1
        if (innerMatch.groups()[1] is not None):          
            print ("Found at {start}-{end}: {group}".format(start = innerMatch.start(2), end = innerMatch.end(2), group = innerMatch.group(2)))

或者继续搜索下一层(上面没有显示)代码。
基本上,您将从 inner 继续以相同的方式从步骤 1 开始再次匹配(参见 demo ),例如:

(?<="c": )({(?>[^{}]|(?1))*})

这应该让您抢先一步。

*由于我们使用正则表达式递归,我们需要替代的 Python 正则表达式包。

关于python - 在 Python 中使用正则表达式匹配 JSON 键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50539399/

相关文章:

Python - 使用 BeautifulSoup 在页面中抓取多个类

python - 预处理使用 keras 函数 ImageDataGenerator() 生成的图像来训练 resnet50 模型

json - 将键值 json 数据读取到 Google Sheet 单元格中

json - 记录 JSON 正文可以,但不能记录 body.item。给出未定义的

java - 如何在正则表达式中指定随机组位置而不是序列?

python - Django 找不到我的媒体文件(在开发服务器上)

java - 我可以使用动态字段从 JSON 有效负载创建 Java 17 记录吗?

javascript - 使用 JavaScript 中的 onblur 事件验证电子邮件

javascript - 替换空格但不替换括号之间的空格

python - 匹配正则表达式(python)