【问题标题】:Regular Expressions, understanding lookbehind in combination with the or operator正则表达式,结合 or 操作符了解后向
【发布时间】:2015-08-07 07:53:14
【问题描述】:

这更多的是理解问题,而不是实际问题。情况说明如下。我在两个引号“”之间得到了一些浮点数(例如金额)。

例子:

  1. “1,23”
  2. “12,23”
  3. “123,23”

现在我想匹配这些表达式中的逗号。我构建了以下适用于我的正则表达式:

(?<=\"[0-9]|[0-9]{2})(,)(?=[0-9]{2}\")

我不完全理解的部分是与或“|”组合的lookbehind。但是让我们分解一下:

(
?<=             //Start of the lookbehind
\"              //Starting with an escaped quotation mark "
[0-9]           //Followed by a digit between 0 and 9

现在我遇到了一个问题,如示例 2 和 3 中所示,引号后并不总是只有一位数字。范围运算符,例如{1,3} 在后视中不起作用。正如我在anotherstackoverflow 问题中发现的那样。

所以我决定使用或“|”建议的操作员here:

|[0-9]{2}       //Or followed by two digits between 0 and 9
)

有趣的是,它还匹配第三个示例中的逗号“123,23”。我真的不明白为什么。 另外我不知道为什么我不必在或“|”之后添加起始引号再次操作符,因为我认为在 or 操作符之前的完整回顾是有必要修改或重复的,例如:

(?<=\"[0-9]|\"[0-9]{2})(,)(?=[0-9]{2}\")            //This however does not work at all

所以在我的理解中,匹配所有三个示例的相应正则表达式应该如下所示:

(?<=\"[0-9]|\"[0-9]{2}|\"[0-9]{3})(,)(?=[0-9]{2}\")

或至少(如果有人能解释丢失的 \"):

(?<=\"[0-9]|[0-9]{2}|[0-9]{3})(,)(?=[0-9]{2}\")

我希望有人能够帮助我了解情况。

//编辑: 如果特别感兴趣,我在 sublime text 3 编辑器的常规文本文件中使用了这个正则表达式来搜索逗号并替换它。

【问题讨论】:

  • (?&lt;=\"[0-9]|[0-9]{2}) 匹配这些示例中的所有逗号

标签: regex sublimetext3 regex-lookarounds


【解决方案1】:

你是对的,

(?<=\"[0-9]|\"[0-9]{2}|\"[0-9]{3})(,)(?=[0-9]{2}\")

在这种情况下应该是正确的正则表达式。


关于为什么您“不需要\" 两位和三位数字” - 您实际上需要它。
(?<=\"[0-9]|[0-9]{2}|[0-9]{3})(,)(?=[0-9]{2}\")

也将匹配 12,23"123,23"


编辑: 看起来问题是 Sublime 不允许可变长度的后视,即使它们以| 列出。意思是(?&lt;=\"[0-9]|\"[0-9]{2}|\"[0-9]{3}) 将失败,因为替代品的大小不同 - 2、3、4

这是因为 Sublime 似乎在使用 Boost library 正则表达式。 There 声明:

往后看

(?&lt;=pattern) 消耗零个字符,前提是模式可以与当前位置之前的字符匹配(模式必须是固定长度)。

(?&lt;!pattern) 消耗零个字符,仅当模式无法与当前位置之前的字符匹配时(模式必须是固定长度)。

另一种方法是将后视分开:

(?:(?<=\"[0-9])|(?<=\"[0-9]{2})|(?<=\"[0-9]{3}))(,)(?=[0-9]{2}\")


如果您不想列出所有可能的长度,该怎么办?

在一些正则表达式引擎(包括 Perl、Ruby 和 Sublime)中有一个很酷的技巧 - \K\K 大致翻译为“删除到目前为止匹配的所有内容”。因此,您可以将浮点数内的任何, 匹配为用引号括起来:

"\d+\K,(?=\d+")

See it in action

【讨论】:

  • 好吧,我的意思是 sublime text 不接受(?&lt;=\"[0-9]|\"[0-9]{2})(,)(?=[0-9]{2}\") 并说以下错误:“在正则表达式中遇到无效的lookbehind assertion”,与(?&lt;=\"[0-9]|\"[0-9]{2}|\"[0-9]{3})(,)(?=[0-9]{2}\") 相同。但是是的,"\d+\K,(?=\d+") 在特定情况下工作得很好。谢谢你。也许这只是崇高文本的问题,而不是正则表达式本身的问题?
  • 如果只是 sublime text 的问题,我可以忍受。非常感谢您提供这个答案。这对我的理解很有帮助。
  • 我做了一些进一步的调查并更新了我的答案,以解释为什么 Sublime 有这个限制以及如何解决它。
  • 再次感谢您的努力。我真的很感激。
猜你喜欢
  • 2012-10-30
  • 1970-01-01
  • 2012-12-03
  • 2011-10-10
  • 2018-05-07
  • 1970-01-01
  • 1970-01-01
  • 2011-01-03
  • 1970-01-01
相关资源
最近更新 更多