2015-10-01 26 views
3

我期待这只匹配<style的第一个实例,因为第二个,在空间之后有我放入负向预览的模式。如何在Ruby Regex中正确使用lookahead?

"<style type=\"text/html\">ciaoxocs <style />".scan /<style\s?(?!\/>)/ 
# => ["<style ", "<style"] 

我要为这里发生了什么的解释,可能是一个更好的解决方案,而无需结束标记有或没有空间匹配只匹配第一个实例:

<style /> or <style/> 

在regex101.com ,它的工作原理与其他LANGS预期:

https://www.regex101.com/r/pW2oM3/1

+0

以下是一个用于RUBY正则表达式的示例:http://rubular.com/ – mhutter

+0

这不是我要求的 – ciaoben

+0

这不是一个答案。 – mhutter

回答

1

注意的第二场比赛(其中来自<style />)为<style,(无空格),而非<style(与空间结束,不知为何,你不能在这里看到的差异)。您的负面预测(?!\/>)/<style\s?(?!\/>)/只禁止\/>来自子字符串匹配<style\s?后。如果与正则表达式的这部分相对应的匹配字符串是<style(没有空格),那么紧跟在原始字符串后面的是空格(而不是\/>),所以满足否定条件。

如果你确信你想一直匹配的模式有一个空间,那么你可以简单地使空间强制性的,你将只能得到你想要的东西:

"<style type=\"text/html\">ciaoxocs <style />".scan /<style\s(?!\/>)/ 
# => ["<style "] 

如果你不能确定关于这一点,然后将可选空间移入负向预览。

"<style type=\"text/html\">ciaoxocs <style />".scan /<style(?!\s?\/>)/ 
# => ["<style"] 
+1

我为什么要讨厌这个?反正好的回答,我明白我在想什么 – ciaoben

-2

你可能想使用String#match,而不是String#scan迭代地应用模式,直到达到字符串结尾。

> "<style type=\"text/html\">ciaoxocs <style />".match(/<style\s?(?!\/>)/).to_a 
=> ["<style "] 
+1

它不是我要求的 – ciaoben

+0

真的吗?它完全符合你的问题所需的结果[链接](https://www.regex101.com/r/pW2oM3/1)。 – joanbm

+0

如果您确实期望获得不同的结果,请将*准确*放在原始字符串的哪一部分应匹配。 – joanbm

2

问题来自回溯机制。让我们来看看关闭标记发生什么情况的描述:

<script\s?匹配"<script "(?!/>)失败。在这种情况下,回溯机制开始,数量符号逐个回送它们的字符,直到模式成功。在我们的情况下,唯一的可能性是从\s?退回空间。
经过此回溯步骤,<script\s?匹配"<script"(此时没有空格)和(?!/>)条件成功与" />"

有几种可能性来防止这种机制:

  • 使用的原子团(?>...)(即禁止回溯对于子图案一旦达到闭括号):<script(?>\s?)(?!/>)
  • 使用所有格量词0​​(即禁止回溯为量词):<script\s?+(?!/>)
  • 包括在先行的空间:<script(?!\s?/>)\s?
+1

谢谢,很清楚 – ciaoben