2014-10-31 15 views
1

處理一些文本格式和分析 - 我有一大塊文本,我試圖分解成單個句子。顯然,explode可以輕鬆地在每句句尾使用標點符號。如何在使用preg_replace時保持某些字符不變?

我遇到的問題是普通語言也包含句點,不表示句子結尾 - 例如小數和縮寫。例如,「一個團隊預計他們將打破之前創造的效率爲92.49%的紀錄,該紀錄是1991年制定的。」將導致兩個句子,第二個以「49%」開始。這是我想要避免的。

我可以安全地刪除這些中期句子,而不會影響我的分析,但是我需要保持每個字符串的其餘部分不變 - 這就是我遇到麻煩的地方。在上述小數點的情況下,我可以將該字符與$str = preg_replace("/[\.]+[0-9]/", "", $str);匹配 - 但是替換該匹配也會消除數字的第一個小數。

如何使用preg_replace並仍保持某些字符不變?


UPDATE:

一對夫婦的答案都使用一個超前而不包括它在更換匹配的字符建議。雖然這適用於上面給出的例子,但這不適用於縮寫(例如美國) - 是否存在我們可以提出的更普遍的情況,或者至少可能是對手「向後看」?

+1

有趣的案例。請注意,有更多的案例可以包含一個點,如abreviations和名稱。如果這些句子被解析爲句子,您是否希望將其考慮在內或者不是問題? – vrijdenker 2014-10-31 18:26:27

+0

請在字符串前後顯示我們(編輯問題,請勿將它置於註釋中)。 – 2014-10-31 18:28:31

+0

@vrijdenker這是一個很好的觀點,特別是縮寫(例如美國)提出了同樣的問題。我將編輯該問題以適用於更一般的情況。 – CodeMoose 2014-10-31 18:32:55

回答

-1

嘗試$str = preg_replace("/[\.](+[0-9])/", "$1", $str);

0

,如果你調整你的正則表達式匹配,其中一些圍繞小數點......這樣的事情也許

/[0-9]+[\.][0-9]+/ 

編輯:

如何匹配那麼替換?

preg_match_all("/[0-9]+[\.][0-9]+/", $str, $out, PREG_PATTERN_ORDER); 

然後遍歷$ out數組並執行替換這些字符串以刪除小數。

+0

感謝您的輸入,但是如果替換它,會在小數點前後立即刪除數字。 – CodeMoose 2014-10-31 18:33:43

0

我認爲這應該爲你工作:

[\.](?=[0-9]) 

它使用一個超前匹配一個小數,隨後0-9,但沒有包括在比賽中0-9。

更新:

我又看看它充分考慮您的更新,但我不能認爲解決所有的用例的解決方案的。我能夠做我建議多一點一般覆蓋更多的情況與此解決方案:

[\.](?=[^\s]) 

這看起來一段或小數點字符後跟任何不是空格,製表符,換行符,等等,而不僅僅是一個數字。這有助於捕捉更多可能會導致問題的事情,但仍然會有很多錯誤。

這東西在工作本:

「一個團隊預計,他們將打破92.49%的效率,這是在1991年在美國創下的原紀錄」

,但會失敗,這樣的事情:

「一個團隊預計,他們將打破92.49%的效率,這是在美國於1991年創下的原紀錄」

正如@vrijdenker提到的,名字是另一個問題。我只是不知道你是如何區分句子末尾的一段時間和縮寫中間首字母后的時段。

+0

這可能適用於此特定示例,但如果我們需要匹配「美國」與'「/ [A-Z] + [\。] /」'?有沒有可以使用的「lookbehind」? – CodeMoose 2014-10-31 20:01:57

0

嘗試:

$str = preg_replace("/\.(?=\d)/", "", $str); 
+0

查看我對@twalters的評論 - 有些情況下,lookahead將無法捕捉。我們可以使用更普遍的情況嗎? – CodeMoose 2014-10-31 20:02:30

+0

是的,你可以用縮寫:(?<= \ w)\。(?= \ w) – Croises 2014-10-31 20:15:23

0

既然你不想忽略屬於僅數點,但還可以使用縮寫,姓名等,只是忘記了一會兒的數字。

我已經設置了一個包含一些Lorem Ipsum的小提琴,在中間我添加了你的例句,後面跟着一些更多的縮寫和名字。

<?php 


$var = <<<EOT 
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam tortor velit, facilisis ac malesuada vel, tristique sit amet purus. 
Donec magna turpis, iaculis vitae nisl et, porttitor tincidunt augue. Fusce odio tortor, laoreet ut turpis eget, lobortis ultrices lorem. 
One team anticipates they will break the previous record of 92.49% efficiency, which was set in 1991. B.T.W.: abbreviations like U.S. and names like I.M. Theman should also be ignored. 
Duis lobortis lacus ligula, a lobortis ipsum lacinia in. Suspendisse potenti. Donec mattis volutpat nisi, non cursus est. Nam pellentesque congue lectus, in auctor erat viverra sit amet. 
Mauris pellentesque magna dolor, in euismod neque mattis eu. Etiam in massa eget eros consectetur iaculis eu in tortor. 
Mauris luctus, nulla ac blandit molestie, augue dui iaculis orci, eu suscipit ipsum mauris a enim. Curabitur vel mauris lorem. Maecenas et metus cursus, posuere nisi vitae, auctor turpi. 
EOT; 

$var = preg_replace('/[^\.]{2,}\.\s/', '$0[[SPLIT]]', $var); 
$lines = explode('[[SPLIT]]', $var); 

print_r($lines); 

如果你看一下文本可以彌補以下邏輯:

  • 在句點結束,應始終遵循由空格:空格或一個換行符
  • 縮寫後面還跟着空格。在很多情況下,儘管它只有一個字符。一個句子永遠不會以單個字符結尾(我認爲),所以讓我們說,在點之前,必須有多於一個字符不是空格或點。

這個邏輯讓下面的正則表達式:

/[^\.]{2,}\.\s/ 

正如你可以在這裏看到,該作品:http://ideone.com/MkyEcL

請注意以下事項:

  • 您可以用preg_split()來做到這一點,但正如你在我的例子中看到的那樣,我試着保持文本的完整性。所以我保留點,空格和換行符。我不知道如何用preg_split做到這一點,所以我已經將preg_replace()和explode()結合起來了。
  • 另請注意,我可以考慮我認爲無法捕捉的病例。例如以下語句:

    「我是Theman先生,我愛StackOverflow。」

    在這種情況下,縮寫有多個字符,後面跟着空格,甚至後面的字符也是大寫字母。我認爲在正則表達式中捕獲這種情況根本不可能,因爲您只需知道它是否是縮寫。

相關問題