【问题标题】:How to handle spaces in values if you use spaces as a delimiter with regex?如果将空格用作正则表达式的分隔符,如何处理值中的空格?
【发布时间】:2019-11-26 13:13:55
【问题描述】:

我正在尝试运行正则表达式来捕获以下字符串的键和值:

name="Evoke Sprite" parent="EvokeObjects" instance=ExtResource( 5 ) id=5

这里有一些语法注释如下:

  • 键:一串字母,没有空格
  • 价值观:

    • 可能有引号,例如。 “唤起对象”
    • 引号内可能有空格
    • 引号内可能有特殊字符,例如“hello/world@!18”
    • 可能有类似字符串 ("ExtResource( 5 )") 的函数。
    • 函数字符串的括号内有空格

我已经知道在引号中有空格了:

(.*?)=(?:"(.*?)"|(.*?))(?: |$)

所以这将适用于 name="Evoke Sprite" parent="EvokeObjects" id=5

要测试的正则表达式101:https://regex101.com/r/xkRRsD/1

当我添加ExtResource( 5 ) 时会出现问题,因为它在括号内有空格。那么前面的正则表达式代码就失败了。

作为一种可能的解决方法,我在想也许我可以通过在代码中进行字符串替换来完全删除括号中的空格。但我想知道是否有正则表达式解决方案?

【问题讨论】:

  • "一串文本,没有空格" 你的意思是一串字符,还是一串字母?无论哪种方式。 .*? 不是,因为它包含空格。
  • 如果输入是#$%^=*@( !<>),那是一个有效的键#$%^/值*@( !<>)组合吗?
  • 你能有没有"即key=some value some random value的字符串字符串作为值吗
  • @CodeManiac 在这种情况下,如果它需要空格,它将带有引号,所以我不必担心这种情况。
  • @Andreas 很可能只有字母。不会有任何特殊字符,也不会有任何数字。对于值,带引号的字符串可以包含特殊字符,例如"hello/world@!"。

标签: java regex


【解决方案1】:

在交替的第二部分中,匹配到空格或字符串的结尾,以便匹配ExtResource(

你可以做的是要么不匹配括号,要么匹配从左括号到右括号。

您可以使用negated character class,而不是使用非贪婪量词。

([^=\s]+)=(?:"([^"]+)"|((?:[^\s()"]|\([^()]*\))+))

说明

  • ([^=]+)= 捕获组 1,匹配除 = 之外的任何字符,然后匹配 =
  • (?: 非捕获组
    • "([^"]*)" 匹配“,然后在第 2 组中捕获除“之外的任何字符,然后匹配”
    • |或者
    • (捕获组3
      • (?:非捕获组
        • [^\s()"] 匹配除(、)、" 或空白字符以外的任何字符
        • |或者
        • \([^()]*\)从左括号到右括号匹配
      • )+关闭非捕获组并重复1次以上
    • )关闭第三组
  • )关闭非捕获组

Regex demo

【讨论】:

  • @Andreas 你是对的,谢谢你。我已经更新了。
  • @Andreas 现在它也会匹配这些。
  • 不确定 a= 是否应该与键 a 匹配,值为空。要求中没有任何内容排除它。你的正则表达式不匹配。但是,无论如何,将我的反对票改为赞成票。
  • 谢谢您(以及您的反馈)。让我们等待 OP 澄清那部分,我会相应地更新它。
  • 这很好,我想我可能需要做一些前瞻,但这是一个更简单的解决方案。我承认,我对否定字符类有点陌生,但你的清晰解释对我有很大帮助。
【解决方案2】:

编辑:v5,这应该会影响@Andreas 的所有测试用例。

看起来您的正则表达式非常接近,但您的非捕获组中的最后一条语句(.*?) 会将左括号后的空格视为其搜索的“结束”,因为它消耗的很少在碰到空格之前尽可能多的字符。鉴于您知道函数字符串在括号之间会有空格,这个正则表达式似乎可以解决问题:

(\S*?)=(?:"(.*?)"|(\S*?\(.*?\))|(\S*?))(?: |$)

至关重要的是,\S 匹配任何非空白字符 - 因为永远不会有像 id=some val 这样的示例,这是一个很好的选择,因为它不会超出函数中的括号。它还确保键名没有空格,例如pare nt=val。

Try it here!

【讨论】:

  • 好收获。我会调查一下,看看我能找到什么。
  • @Andreas 看起来我遇到了你提到的情况 - 请参阅更新。
  • 是否应该匹配错误的输入?例如。 a=b(5)c) 还是 a="b"c?我会说不。或者至少只匹配有效部分b(5) 和"b"。但是,可以解释,所以删除反对票。
【解决方案3】:

你可以使用

([a-z]+)=(?:"(.*?)"|(.*?))(?:(?=[a-z]+?=)|$)

Regex Demo

【讨论】:

  • 根据规则不匹配name=Evoke Sprite parent=EvokeObjects。规则指定值中的空格只能在引用或括号内出现。
  • @Andreas OP 确认没有such case,无论如何感谢您的反馈
  • 我不知道我是否可以在 cmets 中问这个问题,但我喜欢你那里的图片。你是怎么生成的?
  • @Flare 这就是开源的美妙之处在于人们喜欢分享知识,这是使用Regex visualizer生成的
猜你喜欢
  • 2019-11-29
  • 1970-01-01
  • 2021-12-27
  • 2015-03-23
  • 2012-03-30
  • 2020-08-29
  • 1970-01-01
  • 2018-11-19
  • 1970-01-01
相关资源
最近更新 更多