簡體   English   中英

我需要一個正則表達式來匹配字符串的第一個句子

[英]I need a regex to match first sentence of the string

我正在嘗試提出一個匹配字符串第一句的正則表達式。 我不需要任何太復雜的東西,只需要以“。”或“!”或“?”結尾的句子注意后面的空格,以便句子“我需要這個域名!”將匹配。 我在regexlib.com上也找不到任何東西。 到目前為止,我堅持這個:

([^.|?|!]*)[\.\s\?\s\!\s]

它並沒有真正起作用。 如果我試着匹配

"I need this domain.com! Another sentence. And another sentence."

我只得到“我需要這個域名。” 我需要它“我需要這個域名!”

嘗試這個 :

^.*?[\.!\?](?:\s|$)

這是一個通過原始測試的模式,同時也解決了Vitali Ponomar關於manji答案的括號的評論。

^.*?[.!?](?:\s|$)(?!.*\))

這使用否定的前瞻來有效地說:

  1. 從頭開始並匹配任何字符,任意次數,但盡可能少,仍允許以下內容成立。
  2. 我們看到其中一個字符: . 還是 ? 或者 !
  3. 接下來是:空格字符行尾
  4. 其后沒有任何導致a )右括號字符的東西。

這利用了這樣一個事實,即只要它是平衡的,我們就知道括號組的結束位置。 因此,如果由於用戶輸入或處理不當等而導致句子格式錯誤,則可能會失敗。

您可以通過斷言“句子的開頭”標記必須包含大寫字符來添加一定程度的保護。

^.*?[.!?](?:\s[A-Z]|$)(?!.*\))

這是可取的原因是因為,在大多數程序中,在連接字符串之前大大簡化字符串與確保括號在其中進行適當平衡相比要容易得多。

請注意,因為OP使用非捕獲組接受了答案,如(?:foo) ,我也使用了一個。 這將導致“句子的開頭”標記包含在匹配中。 您可能會也可能不會想要這個,這取決於您是僅依靠空格字符還是我添加的大寫檢查。

我的建議是不要包含它,你可以通過使用前瞻來做,比如(?=foo)

^.*?[.!?](?=\s[A-Z]|$)(?!.*\))

既然我們沒有在比賽中包括殘骸,那么讓我們來處理在我們的第一句話之后只有空格的情況:

^.*?[.!?](?=\s[A-Z]|\s?$)(?!.*\))

現在一些測試與這個相當不錯的模式:

  • 輸入 :“我需要這個域名!另一句話。另一句話。”

    匹配 :“我需要這個domain.com!”

  • 輸入 :“這是第一個(例如第一個)句子。第二個。”

    匹配 :“這是第一個(例如第一個)句子。”

  • 輸入 :“這是一個破碎的(例如第一句。第二句。”

    匹配 :“這是一個破碎的(例如第一句。”

  • 輸入 :“這最讓人興奮......但不是我。”

    匹配 :“這最讓人興奮......”

大。 但仍有一些地方會倒塌。 例如:引號。 句子很復雜! 要做到這一點,你真的需要考慮給定語言的整個標點規則,然后提出一個算法,它不會假設每個人都會完全遵循它們,並且在不引入奇怪匹配的情況下使某些部分成為可選項。 一旦你沿着那條路走下去,你就會得到一個很長的,不可讀的表達式,里面有很多貪婪的算子 (某些用於?問號)。

最后,它主要取決於程序的輸入是什么樣的,它來自何處,以及在對其應用復雜模式匹配之前如何預先處理它。 通常,它更可靠,更易讀,但性能更低,可以進行更小,更簡單的模式的多次傳遞。 一個用於刪除或刪除您不關心的內容(如換行符或其他空白字符),然后刪除可能的惡意輸入痕跡,等等。隨着輸入的簡化,慢慢變得越來越復雜。

沒有測試但是應該這樣做

^([^.|?|!]+)

問題是*匹配零個或多個字符,而+匹配至少一個字符

(我將使用Java正則表達式語法編寫,因為這就是我所知道的;它應該與我們使用的任何其他正則表達式系統相同,但我不是百分之百確定。)

句子邊界的正則表達式顯然是[.!?]\\s 所以,你希望將所有內容與第一個相匹配。 “。+”貪婪地匹配並匹配最后一句開頭的所有內容。 你想要一個不情願的捕獲:

(.+?)[.!?]\\s

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM