为啥正则表达式可选非捕获组不作为可选并且搞砸匹配?
Posted
技术标签:
【中文标题】为啥正则表达式可选非捕获组不作为可选并且搞砸匹配?【英文标题】:why is regex optional non-capture group not acting as optional and screwing up matches?为什么正则表达式可选非捕获组不作为可选并且搞砸匹配? 【发布时间】:2012-10-01 05:03:12 【问题描述】:我正在使用第 3 方应用程序,它使用正则表达式来搜索 html 文档,在这种情况下,它没有正确的结构(没有头部或正文),并将匹配项作为属性形式返回excel文件。它不会解析它们。我已经知道尝试使用正则表达式解析 html 会带来怎样的恐惧。
所以我写了一个正则表达式,它应该捕获段落或列表项中的每个句子,但在检查匹配项后,我注意到有时它不会匹配所有句子,并且一旦该句子或列表项给出一个错误。几乎总是用列表项,但偶尔用句子。在意识到这是由于人为错误造成的之后,我添加了可选的非捕获组,这完全搞砸了一切。
这是我编写的最初的正则表达式,在大多数情况下都有效:
([^<>]*?)[.!?<]|[ <"'/]
由于有些句子作者在标点符号前加了一个空格有错误,所以我添加了可选的非捕获组:
([^<>]*?)(?:[ ])?[.!?<]|[ <"/l]
这是它正在搜索的文本示例:
Buy this because it is soooooooooooooooooooo freaking awesome! If you buy this
everyone will think you're "cool." You'll get all the babes !<br><br><ul><li>It
will make you smell better<li>It will make you preform better.</li><li>Will make
you last longer in bed!<li>Will fix any acne problem.</li> <li>It will reduce the
amount you perspire to .01% your normal amount!<br><li>It will make you
"invincible."</li></ul>
因为它们不能用作锚点(文本从 html 文件的开头开始),所以我只是让它立即开始捕获。如您所见,它的编码很差,并且有语法错误,这就是我以这种方式结束它的原因。
第一个捕获了所有句子,但遗漏了一些......第二个返回一堆空匹配的空白,这搞砸了由捕获组成的数组。 这就像它在非捕获组之后无视一切。
我曾想过这样做,但这会将每个单词都返回为匹配项:
([^<>]*?)[ .!?<]|[ .!?<"/l]
唯一的问题是这会在中间删掉一些句子,并且需要第三个范围,我认为这会有很多不同的选项(注意随机的 <br>
标签)并且需要一段时间才能找到它们。
从外观上看,它并没有使用可选的非捕获组!为什么是这样?还是我忽略了一些非常简单的事情?我觉得可能是后者。
【问题讨论】:
正确使用这个正则表达式和“你会得到所有宝贝”? 哈哈哈哈,如果是这样的话。只是在展示一个假广告 【参考方案1】:我想出了这个野兽:
(?:^|\s+|>)((?:[^<>.!?\s])(?:[^<>.!?]|\.\d)+(?:\.(?!\d)"?|!|\?)?)
让我试着解释一下我在这里做什么。
(?:^|\s+|>) # only start after at the string's beginning, after a row of
# spaces, or after closing a tag
# this eliminates all in-tag matches (like "li" and "br")
( # opening a capturing group that will contain the actual match
(?:[^<>.!?\s]) # require at least one character that is not in the given group
# this eliminates matching a single space between two <li>s
# NOTE: there are probably better ways to do this
(?:[^<>.!?]|\.\d) # defines possible sentence characters; allow everything but
# <, >, ., !, ? EXCEPT FOR . followed by a digit
(?:\.(?!\d)"?|!|\?)?
# include possible sentence endings; that is . not followed by
# a digit (hence, the negative lookahead), but possibly
# followed by ", or !, or ?, or nothing at all
) # close the main matching group
现在您应该可以在捕获的索引1
处访问您的句子了。
我相信您可能会遇到这样的情况,即我对句子的假设可能会被打破。但我只能从你给出的例子中工作,其中所有的奇怪之处都包括在内。
【讨论】:
天哪,这是一个很棒的正则表达式。完成手头的任务后会试一试!以上是关于为啥正则表达式可选非捕获组不作为可选并且搞砸匹配?的主要内容,如果未能解决你的问题,请参考以下文章