正则表达式,与or运算符一起理解lookbehind

Kev*_*vin 1 regex regex-lookarounds sublimetext3

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

例子:

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

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

(?<=\"[0-9]|[0-9]{2})(,)(?=[0-9]{2}\")
Run Code Online (Sandbox Code Playgroud)

我不完全理解的部分是与"或"结合的外观.但是让我们分手吧:

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

现在我遇到了问题,在引号后并不总是只有一位数,你可以在例子2和3中看到.范围运算符例如{1,3}在lookbehind中不起作用.正如我在另一个 stackoverflow问题中发现的那样.

所以我决定使用或者"|" 操作员在这里消化:

|[0-9]{2}       //Or followed by two digits between 0 and 9
)
Run Code Online (Sandbox Code Playgroud)

有趣的是它也匹配第三个例子"123,23"中的逗号.我真的不明白为什么.另外我不知道为什么我不必在"|"之后添加起始引号 操作员再次,因为我认为完整的lookbehind直到或运算符将被修改或重复,例如:

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

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

(?<=\"[0-9]|\"[0-9]{2}|\"[0-9]{3})(,)(?=[0-9]{2}\")
Run Code Online (Sandbox Code Playgroud)

或至少(如果有人可以解释失踪的""):

(?<=\"[0-9]|[0-9]{2}|[0-9]{3})(,)(?=[0-9]{2}\")
Run Code Online (Sandbox Code Playgroud)

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

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

ndn*_*kov 6

你是对的,

(?<=\"[0-9]|\"[0-9]{2}|\"[0-9]{3})(,)(?=[0-9]{2}\")
Run Code Online (Sandbox Code Playgroud)

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


关于为什么你"不需要\"两位和三位数" - 你实际上需要它.

(?<=\"[0-9]|[0-9]{2}|[0-9]{3})(,)(?=[0-9]{2}\")
Run Code Online (Sandbox Code Playgroud)

将匹配12,23"123,23"为好.


编辑:看起来问题是Sublime不允许可变长度的lookbehind,即使它们被列出|.意义(?<=\"[0-9]|\"[0-9]{2}|\"[0-9]{3})将失败,因为替代品的大小不同 - 2,3,4.

这是因为Sublime似乎正在使用Boost库正则表达式.在那里说:

向后看

(?<=pattern)仅当模式可以与当前位置之前的字符匹配时(模式必须是固定长度),才会消耗零个字符.

(?<!pattern)仅当模式无法与当前位置之前的字符匹配时(模式必须具有固定长度),才会消耗零个字符.

另一种方法是分离外观:

(?:(?<=\"[0-9])|(?<=\"[0-9]{2})|(?<=\"[0-9]{3}))(,)(?=[0-9]{2}\")
Run Code Online (Sandbox Code Playgroud)


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

在一些正则表达式引擎中存在一个很酷的技巧(包括Perl,Ruby和Sublime) - \K.什么\K大致翻译为"删除所有到目前为止这是匹配的".因此,您可以匹配,引号括起的浮点数中的任何一个:

"\d+\K,(?=\d+")
Run Code Online (Sandbox Code Playgroud)

看到它在行动