2012-11-18 30 views
2

這是一句殺菌劑。優化正則表達式的語句消毒劑

function sanitize_sentence($string) { 
    $pats = array(
    '/([.!?]\s{2}),/',  # Abc. ,Def 
    '/\.+(,)/',    # ......, 
    '/(!|\?)\1+/',   # abc!!!!!!!!, abc????????? 
    '/\s+(,)/',    # abc , def 
    '/([a-zA-Z])\1\1/'); # greeeeeeen 
    $fixed = preg_replace($pats,'$1',$string); # apply pats 
    $fixed = preg_replace('/(?:(?<=\s)|^)[^a-z0-9]+(?:(?=\s)|$)/i', '',$fixed); # bad chunks 
    $fixed = preg_replace('/([!?,.])(\S)/', '$1 $2', $fixed); # spaces after punctuation, if it doesn't exist already 
    $fixed = preg_replace('/[^a-zA-Z0-9!?.]+$/', '.', $fixed); # end of string must end in period 
    $fixed = preg_replace('/,(?!\s)/',', ',$fixed); # spaces after commas 
    return $fixed; 
} 

這是測試一句話:

你好[[[[[[]]]]]]朋友.....?你怎麼樣[}}}}}}

它應該返回:

招呼朋友.....?你怎麼樣

但是,相反它返回:

招呼朋友。 .. ..?你好嗎。

因此,有2個問題,我無法找到他們圍繞一個解決方案:

  1. 設定的時間段被分成「.. ..。」因爲某些原因。它們應該在問號旁邊保持爲「.....」。
  2. 如果字符串中的任何位置至少有一個字符,則字符串的結尾必須僅在且僅有的句點結束:!?,。(如果在字符串中沒有找到的那些字符中的至少一個,即preg_replace函數應該不被執行)
  3. 對於第二個問題

實例:

這個句子沒有需要一個結束期間因爲提到的字符無處可尋

這個其他的句子,需要它!爲什麼?因爲它含有以上列出的字符

的至少一個

感謝您的幫助(當然,期末應只如果它不存在,就放在)!

+5

通過正則表達式的英語語法驗證永遠不會結束。 – 2012-11-18 21:35:14

+0

如果您不能通過正則表達式解析(X)HTML,**您想如何解析口語**?它們比某些XML標記更不規則。 – ComFreek

+0

當你有一把錘子,一切看起來像一個釘子... – Toni

回答

4

這是您的第一個問題的答案。第三到最後一個替換的問題是:

$fixed = preg_replace('/([!?,.])(\S)/', '$1 $2', $fixed); # spaces after punctuation, if it doesn't exist already 

它將匹配以字符類的第一個週期,和第二時間段作爲一個非空格字符。然後插入一個空格。由於匹配不能重疊,因此匹配第三個和第四個週期並插入一個空格等等。這可能是最固定的是這樣的:

$fixed = preg_replace('/[!?,.](?![!?,.\s])/', '$0 ', $fixed); 

這裏是你如何能去你的第二個要求(更換第二個到最後preg_replace):

$fixed = trim($fixed); 
$fixed = preg_replace('/[!?.,].*(?<![.!?])$/', '$0.', $fixed); 

首先我們擺脫領導和拖尾的空白將這種擔憂與尾隨時期分開。然後,preg_replace將嘗試在字符串中查找標點符號,如果符合,則會匹配所有內容直到字符串結束。替換將比賽放回原位並追加該時段。請注意負向後視。它斷言該字符串不會以句尾標點符號結束。

+0

我正在測試你的加法,除了最後一次破解之外,它的效果很好,嘿嘿。保留原來的最後一個字符是否可能,以防止它是** **或** ** **,而不是用一段時間替換它? – andufo

+1

@andufo當然,單獨使用'trim'可能無論如何都是更好的方法。看到我的編輯 –

+0

謝謝!很棒! – andufo