2012-09-23 41 views
5

實施例的輸入字符串:test:)test:)test:) :) test:p test
求購輸出字符串:test :) test :) test :) :) test :p test如何在空間尚未存在的情況下在子字符串周圍添加空格?

正如可以在上面的例子中看到的,我想分析字符串和產生輸出字符串周圍的所有預定義的笑臉碼添加空格。

我試圖用一些循環來做到這一點,但最終它沒有像預期的那樣100%工作,而且它在大文檔上的速度非常慢。

所以我想知道什麼是最好的和最有效的方式來做這種解析與PHP?

+5

正則表達式。學習它們,享受它們,並發現在一行'preg_replace'中很容易做到這一點 – Prinzhorn

+0

我之前曾試着用preg_replace()來做這件事,但是由於某種原因它沒有工作。你能幫我在這裏嗎? – Erik

+0

@Prinzhorn我試着'$ text = preg_replace('/([^]):\\)([^])/ i','$ 1 :) $ 2',$ text)',但不起作用。任何想法它有什麼問題嗎? – Erik

回答

0

而不是正則表達式,你可以使用str_replace函數。 PHP函數str_replace可以接收數組作爲參數,所以你可以試試這個:

$input = 'test:)test:)test:) :) test:p test'; 
$smileys = array(':)', ':p'); 
$smileys_with_spaces = array(' :)', ' :p'); 
$output = str_replace($smileys_with_spaces, $smileys, $input); // test:) :) -> test:):) 
$output = str_replace($smileys, $smileys_with_spaces, $input); // test:):) -> test :) :) 
+0

這看起來不像一個可用的解決方案,因爲它會增加過多的空間。例如,它將爲已經有空格的笑臉代碼添加空格。 – Erik

+0

正則表達式是更好的方法。 @xdazz提供了更多適當的解決方案。 – doktorgradus

+0

只需通過'str_replace('','',$ input);''刪除多餘的空格。 – doktorgradus

0

嘗試:

$str = "test:)test:)test:) :) test:p test"; 
$str = preg_replace('/(?<=[a-z])(?=[^a-z\s])|(?<=[^a-z]{2})(?=[a-z])/', ' ', $str); 
+0

當兩個笑臉代碼相鄰時,這一個不起作用。因此,$ str是「:) :)」,它不會添加任何空間 – Erik

+0

@Erik你是否修復了圖案? – xdazz

0

更新與支持N個表情

$smile = array(':)', ':p'); 

//Escape smiley chars for use in rx 
foreach($smile as &$s) { 
    $s = preg_quote($s, '/'); 
}unset($s); 

$rx = implode('|', $smile); 

$str = 'test:)test:)test:) :) test:p test'; 

$str = preg_replace('/ *('.$rx.') */', ' $1 ', $str); 
$str = preg_replace('/('.$rx.') +/', '$1 ', $str); 

echo $str; 
+0

這是一個工作,但它會添加太多的空間,如果兩個笑臉代碼彼此相鄰。例如「:) :)」將成爲「 :) :) 」,而我需要「:) :)」在這個例子中。 – Erik

+0

任何想法如何解決這個問題? – Erik

+0

此更新仍然不會修復字符串開頭或結尾的過多空格。而且我不能使用trim(),因爲如果原始文件在開頭或結尾有空格,它必須保持這種方式。 – Erik

2

嵌套更換:

preg_replace("/\s\s+/", " ", 
    str_replace(Array(":)", ":p"), 
     Array(" :) ", " :p "), $str)); 
0

如果你也想沒有在開始/結束多餘的空格,試試這個:

$str = ':):)test:)test:)test:) :) test:p:) test'; 
$codes = array(
    ':)', ':p', // Add smileys here. 
); 

// We build the $regexp automatically 
$regexp = array(); 
foreach($codes as $smiley) 
    $regexp[] = preg_quote($smiley, '#'); 
$regexp = implode('|', $regexp); 
// Afterwards, we might replace the above with $regexp = 'VERYCOMPLICATEDSYNTAX'; 

// Split the string at smileys, trimming the smileys as we go, 
// and returning an array of smiley-and-non-smiley parts, except for empty ones 
$parts = preg_split("#\s*($regexp)\s*#", $str, -1, 
    PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE); 

// The new delimiter is a single space. 
$str = implode(' ', $parts); 

請注意,我用的空白匹配\s而不是字面空間;如果您在原始字符串中有換行符,這可能會產生不想要的結果。如果是這種情況,請將「\s」替換爲「」字面空格。

0

應該有一個更優雅的解決方案,但下面的代碼應該工作

$patterns = array(); 
$replacements = array(); 

$str = ':) test :)test:) test :)'; 

$smileys = array(':)', ':p'); 

foreach($smileys as &$s) { 
    $s = preg_quote($s, '/'); 
}unset($s); 
$escaped_smiley = implode('|', $smileys); 

$patterns[] = '/([^\s])('.$escaped_smiley.')([^\s])/'; // no spaces 
$patterns[] = '/([\s])('.$escaped_smiley.')([^\s])/'; // space on left 
$patterns[] = '/([^\s])('.$escaped_smiley.')([\s])/'; // space on right 

$patterns[] = '/^('.$escaped_smiley.')([\s])/'; // line starting, space succeding 
$patterns[] = '/^('.$escaped_smiley.')([^\s])/'; // line starting, no space 
$patterns[] = '/([\s])('.$escaped_smiley.')$/'; // line ending, space preceeding 
$patterns[] = '/([^\s])('.$escaped_smiley.')$/'; // line ending, no space 

$replacements[] = '$1 $2 $3'; // no spaces 
$replacements[] = '$1$2 $3'; // space on left 
$replacements[] = '$1 $2$3'; // space on right 

$replacements[] = ' $1$2'; // line starting 
$replacements[] = ' $1 $2'; // line starting 
$replacements[] = '$1$2 '; // line ending 
$replacements[] = '$1 $2 '; // line ending 


$result = preg_replace($patterns, $replacements, $str); 
echo str_replace(' ', '^', $result); 

[從@Prinzhorn借來的代碼編輯]

+0

這樣輸入字符串就像':)test:)test:)test :) test :)' – Erik

+0

輸出結果是:)test :) test :) test :)注意第一個表情符號代碼末尾的空白處,在最後一個之前。 – Erik

+0

@Erik編輯的代碼考慮了行首和結尾。同時從@Prinzhorn中刪除帶'implode'的'foreach'循環,並用引用'foreach'循環替換引用的表情符號。 – air4x

0

如果您還沒有解決這個問題呢,我想出了與可能工作的解決方案。首先使用空格作爲分隔符來分解字符串,用額外的空格替換表情符號,然後用implode對它們進行rejion。

檢查php fiddle的實施。

1
<?php 

$lspace = str_replace(":"," :","test:)test:)test:) :) test:p"); 
$rspace = str_replace(")",") ",$lspace); 
$out = preg_replace("/\s\s+/"," ",$rspace); 


echo $out; 
?> 

輸出:test :) test :) test :) :) test :p

相關問題