【问题标题】:How to match strings between quotation marks in a better way [closed]如何以更好的方式匹配引号之间的字符串[关闭]
【发布时间】:2021-06-11 11:21:41
【问题描述】:

我有一个 JSON 文件,我需要在不使用任何外部库的情况下读取和加载它,所以我最好的选择是使用正则表达式。我当前用于查找字符串的正则表达式是 \"\\.*\" 但由于某种原因,整个 JSON 文件都是匹配的,所以我得到 "FIRST":"Galina98", "LAST":"Murray856", "SUFFIX":"" 而不仅仅是 "FIRST" 为什么会发生这种情况?我认为点应该转义换行符。

或者有没有更好的正则表达式?我的主要问题是我想要两种模式,一种用于左侧的单词,另一种用于右侧的单词,例如\"\\.*\"::\"\\.*\",我该怎么做?

【问题讨论】:

  • 试试\"([^\"]*)\":\"([^\"]*)\"
  • 感谢 omar,这行得通,但它给了我代码 "FIRST":"Jorge",我想为 "FIRST 提供 1 个正则表达式,为 "Jorge" 提供第二个正则表达式
  • 我猜你可以只做\"[^\"]*\",如果你不在乎哪个是哪个。
  • 你的正则表达式匹配一个引号,一个文字点然后一个引号。即"."。在做任何其他事情之前,请完全删除双反斜杠。

标签: java json regex string match


【解决方案1】:

使用不情愿的量词*? 而不是贪婪的量词*;并为键和值() 捕获组,例如:"(.*?)":"(.*?)"。使用Matcher#find() 搜索每个出现的地方,例如:

var text = """
           "FIRST":"Galina98", \
           "LAST":"Murray856", \
           "SUFFIX":"" \
           """;
var pattern = Pattern.compile("\"(.*?)\":\"(.*?)\"");
var matcher = pattern.matcher(text);
while (matcher.find()) {
    var key = matcher.group(1);
    var value = matcher.group(2);
    ...
}

(.*?).*? 的捕获组

.*? 将匹配任何字符的最小数量(以便匹配表达式的其余部分) - *? 是一个不情愿的量词,因为它试图匹配可能的最短序列;相对于*贪婪的量词,它试图尽可能多地匹配


一种更好/更快的方法,因为 Omar Si 的 suggested 正在使用 [^"]*,也就是说,匹配尽可能多的不是 " 的字符。

所以 Java 模式应该是

var pattern = Pattern.compile("\"([^\"]*)\":\"([^\"]*)\"");

请注意,正则表达式(单独)不是解析的最佳工具(例如,在键或值中包含双引号;换行符;...)

【讨论】:

  • 请注意,使用[^\"]*.*? 更有效,因为.*? 将逐个字符匹配,而[^\"]* 将一次匹配所有非引号。
  • @OmarSi all 正则表达式引擎的处理/匹配是逐个字符的。
  • @Bohemian 也许我说错了。 .*? 将尽可能少地匹配,这意味着它将从引号后的第一个字符开始,并尝试逐个字符匹配,直到找到另一个引号。而[^\"]* 将立即匹配所有非引用的内容,从而减少所需的步骤数。
  • 你可以在这里比较步数regex101.com/r/DgmQCs/1 vs regex101.com/r/DgmQCs/2
  • 对不起,我之前的测试不是最好的。我改为排除模式的编译、匹配器的创建和组的读取;现在在 Samuel V 给出的文本上只有 4 次 find()(也改变了预热和迭代次数)结果:贪婪几乎是两倍快:greedy: 2242,901; reluct: 1181,724
猜你喜欢
  • 2019-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-16
相关资源
最近更新 更多