正则表达式,结合 or 运算符理解 lookbehind

Regular Expressions, understanding lookbehind in combination with the or operator

这与其说是一个实际问题,不如说是一个理解问题。情况说明如下。我在两个引号 "".

之间得到了一些浮点数(例如金额)

示例:

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

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

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

我不完全理解的部分是lookbehind与or“|”的结合。但是让我们把它分解一下:

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

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

所以我决定使用或“|”运算符如建议 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 编辑器的常规文本文件中使用这个正则表达式来搜索逗号并替换它。

你是对的,

(?<=\"[0-9]|\"[0-9]{2}|\"[0-9]{3})(,)(?=[0-9]{2}\")
在这种情况下,

应该是正确的正则表达式。


为什么你 "don't need the \" for two and three digits" - 你确实需要它。

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

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


编辑: 看起来问题在于 Sublime 不允许可变长度的回顾,即使它们被列为 |。意思是 (?<=\"[0-9]|\"[0-9]{2}|\"[0-9]{3}) 会失败,因为备选方案的大小不同 - 2, 3, 4.

这是因为 Sublime 似乎在使用 Boost library regexes. There 上面写着:

Lookbehind

(?<=pattern) consumes zero characters, only if pattern could be matched against the characters preceding the current position (pattern must be of fixed length).

(?<!pattern) consumes zero characters, only if pattern could not be matched against the characters preceding the current position (pattern must be of fixed length).

另一种方法是分离后视:

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


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

一些正则表达式引擎(包括 Perl、Ruby 和 Sublime 的)中存在一个很酷的技巧 - \K\K 大致翻译为 "drop all that was matched so far"。因此,您可以将引号括起来的浮点数中的任何 , 匹配为:

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

See it in action