【问题标题】:How to exclude a line break from regex character class?如何从正则表达式字符类中排除换行符?
【发布时间】:2011-04-24 03:52:48
【问题描述】:

鉴于此 PCRE 模式:

/(<name>[^<>]*<\/name>[^<>]*<phone>[^<>]*<\/phone>)/

还有这个主题:

<name>John Stevens</name>  <phone>888-555-1212</phone>
<name>Peter Wilson</name>  
<phone>888-555-2424</phone>

如何让正则表达式匹配第一个名字-电话对,而不是第二个?我不想匹配由换行符分隔的对。我尝试在否定字符类中包含一个行尾,例如[^&lt;&gt;$]*,但没有任何改变。

您可以使用以下在线工具来测试您的表情:
http://rubular.com/
http://www.regextester.com/
谢谢。

【问题讨论】:

  • 在字符类中,$ 失去了它的特殊含义,变成了一个简单的美元符号。你想要的是:[^&lt;&gt;\r\n] asawa 建议。

标签: regex pcre


【解决方案1】:

我觉得这样就可以了

/<name>[^<>]*<\/name>[^<>\r\n]*<phone>[^<>]*<\/phone>/

无论您在[ ] 类中添加的内容都必须是代表单个字符的内容。 $ 在类中被解释为文字 $,可能是因为 $ 作为行尾是 0 宽度,并且不能在类中被解释为这样。 (由ridgerunner评论后编辑)

顺便说一句,我去掉了围绕你的正则表达式的括号,因为任何匹配它都可以被称为整个匹配。

【讨论】:

  • +1(但 $ 在 char 类中确实有效果 - 它与美元符号匹配。)
  • @ridgerunner 感谢您的指出。我会更正我的答案。
  • 正如 ridgerunner 所指出的,我还添加了 \r。我脑子里只有 unix。
【解决方案2】:

如果你不想匹配由换行符分隔的对,那么下面的正则表达式就可以了:

/(<name>[^<>]*<\/name>.*?<phone>[^<>]*<\/phone>)/

只匹配名字,电话对因为点 . 将不匹配 EOL[^&lt;&gt;] 将匹配它。

http://rubular.com/r/amXvq20sl8上测试过

【讨论】:

  • 谢谢。但我还需要排除&lt;&gt; 以防止捕获其他标签。
  • 在上面设置[^&lt;&gt;]* 并没有什么坏处,但是我认为一旦我们已经在&lt;name&gt; 内部,然后捕获直到&lt;/name&gt;' we just need [
  • 对,我喜欢这种变化。我从主题文本中省略的是,姓名和电话之间可能还有其他标签,如果它们在那里,我不想捕获它们。即&lt;name&gt;Mark&lt;/name&gt;&lt;name&gt;Bill&lt;/name&gt;&lt;phone&gt;888...&lt;/phone&gt;.* 将在同一行捕获两个名称。我知道我可以让它变得懒惰而不是贪婪,但这可能会对我的模式的其他部分产生负面影响。我认为上述\r\n 对我有用。添加您的更改:[^&lt;\r\n].
【解决方案3】:

那些网站似乎不支持整个 PCRE 语法。我用过这个网站: http://lumadis.be/regex/test_regex.php

这很有效:

/^(<name>[^<>]*<\/name>[^<>$]*<phone>[^<>]*<\/phone>)/

/(?-s)(<name>[^<>]*<\/name>.*<phone>[^<>]*<\/phone>)/

可能更好

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-05
    • 1970-01-01
    • 2019-08-03
    • 1970-01-01
    • 1970-01-01
    • 2021-09-16
    • 2021-12-08
    • 1970-01-01
    相关资源
    最近更新 更多