我正在努力想出一个与字符串的第一句匹配的正则表达式。我不需要任何太复杂的东西,只需要以“。”或“!”或“?”结尾的句子注意后面的空格,以便句子“我需要这个域名!”将匹配。我在regexlib.com上也找不到任何东西。 到目前为止,我坚持这个:
([^.|?|!]*)[\.\s\?\s\!\s]
它并没有真正起作用。如果我尝试匹配
"I need this domain.com! Another sentence. And another sentence."
我只得到“我需要这个域名。”我需要它“我需要这个域名!”
答案 0 :(得分:6)
试试这个:
^.*?[\.!\?](?:\s|$)
答案 1 :(得分:2)
这是一个通过原始测试的模式,同时也解决了Vitali Ponomar关于manji答案的括号的评论。
^.*?[.!?](?:\s|$)(?!.*\))
这使用negated lookahead有效地说:
.
或 ?
或 !
)
右括号字符的内容。这利用了这样一个事实,即只要它是平衡的,我们就知道括号组的结束位置。因此,如果由于用户输入或处理不当等而导致句子格式错误,则可能会失败。
您可以通过声明“句子的开头”标记必须包含大写字符来添加一定程度的保护。
^.*?[.!?](?:\s[A-Z]|$)(?!.*\))
这是可取的原因是因为,在大多数程序中,在连接字符串之前将字符串大写更容易,并确保在括号内正确平衡字符串。
请注意,由于OP使用non-capturing组接受了答案,例如(?:foo)
,我也使用了一个。{这将导致“句子的开头”标记包含在匹配中。您可能会也可能不想这样做,具体取决于您是仅依靠空格字符还是我添加的大写检查。
我的建议是不要包含它,您可以使用lookahead来代替(?=foo)
。
^.*?[.!?](?=\s[A-Z]|$)(?!.*\))
现在我们没有在比赛中包括残骸,让我们来处理在我们的第一句话之后只有空格的情况:
^.*?[.!?](?=\s[A-Z]|\s?$)(?!.*\))
现在用这个相当不错的模式进行一些测试:
输入:“我需要这个domain.com!另一句话。另一句话。”
匹配:“我需要这个domain.com!”
输入:“这是第一个(例如第一个)句子。第二个。”
匹配:“这是第一个(例如第一个)句子。”
输入:“这是一个破碎的(例如第一句。第二句。”
匹配:“这是一个破碎的(例如第一句。”
输入:“这最让人兴奋......但不是我。”
匹配:“这最让人兴奋......”
大。但仍有一些地方会倒塌。例如:引号。句子很复杂!要做到这一点,你真的需要考虑给定语言的整个标点规则,然后提出一个算法,它不会假设每个人都会完全遵循它们,并且在不引入奇怪匹配的情况下使某些部分成为可选项。一旦你沿着这条路走下去,你就会得到一个很长的,不可读的表达式,有很多greed operators(?
问号的某些用法)。
最后,它主要归结为程序的输入是什么样的,它来自何处,以及在对其应用复杂模式匹配之前如何预先处理它。通常,它更可靠,更易读,但性能更低,可以进行更小,更简单的模式的多次传递。一个用于删除或删除您不关心的内容(如换行符或其他空白字符),然后用于删除可能的恶意输入痕迹,等等。随着输入的简化,慢慢变得越来越复杂。< / p>
答案 2 :(得分:0)
尚未测试,但应该这样做
^([^.|?|!]+)
问题是*匹配零个或多个字符,而+匹配至少一个字符
答案 3 :(得分:0)
(我将使用Java正则表达式语法编写,因为这就是我所知道的;它应该与我们使用的任何其他正则表达式系统相同,但我不是百分之百确定。)
句子边界的正则表达式显然是[.!?]\s
。所以,你希望将所有内容与第一个相匹配。 “。+”贪婪地匹配并匹配最后一句开头的所有内容。你想要一个不情愿的捕获:
(.+?)[.!?]\s