2017-06-23 29 views
9

我目前有兩個數組設置,並且我試圖檢查單詞中的最後兩個字母,並用其他字符替換它,如果與第一個數組匹配。我現在正在努力做到這一點,但我不知道如何做到這一點,對於不在行尾的單詞。檢查並替換行尾或空格前的字符

以下是我的數組可能看起來像的一個示例。這些從數據庫查詢填充。這些字符可以是任何Unicode字符,因此不一定在A-Z或a-z範圍內。

$array1 = ['mp', 'tm', 'de', 'HK']; 
$array2 = ['MAP', 'TM', "DECIMAL", '字']; 

我當前的代碼如下所示:

$mystring = "samplemp"; 
$last = substr($mystring, -2); 
$newlast = str_replace($array1, $array2, $last); 
if ($last != $newlast){ 
    $mystring = substr($mystr, 0, 2).$newlast; 
} 

我所工作:

所以,我現在有代碼看起來在字符串中的最後兩個字符。例如,如果最後兩個字符是「mp」,則用「MAP」替換它們。所以,如果我的字符串看起來像:

samplemp 

它被正確地改爲

sampleMAP 

至此一切正常。

問題

我有正在處理不在一個字符串末尾的字的問題。例如:

samplemp okay de  hellotm 
blatm theHK end 

sampleMAP okay DECIMAL  helloTM 
blaTM the字 end 

我希望能夠考慮到所有空白,包括空格,製表符和回車替換。但是,空格必須保持完整並且不能更改。空格必須保留爲空格,製表符作爲製表符,並且回車符作爲回車。

到目前爲止,我已經能夠弄清楚,我可能需要使用正則表達式使用\s轉義字符來解釋空白。但是,我無法理解如何將str_replace函數用於數組。有沒有辦法做到這一點?如果沒有,我還應該做些什麼才能使其發揮作用?

+0

你缺少一個'$'這裏'$ myString的= SUBSTR($ mystr,0,2).newlast;'應該是'$ mystring = substr($ mystr,0,2)。$ newlast;' – ArtisticPhoenix

+0

感謝您的幫助@ArtisticPhoenix,我沒有想到提到的一件事是字符不一定是拉丁字符,而是任何Unicode字符。所以,a-z範圍將不起作用。我認爲你可能會對preg_replace函數有所瞭解,但我將不得不更多地關注它,試圖搜索空白區域。另外,謝謝你指出我缺少的$。我的真實代碼中有$,只是在我的示例中錯過了它。 – kojow7

+0

您遇到的問題是str_replace,將取代任何出現的字符串。 preg_replace或Regx通常會讓您更​​好地控制匹配發生的位置。 – ArtisticPhoenix

回答

4

我會怎麼做:

$string = <<<EOD 
samplemp okay de  hellotm 
blatm theHK end 
EOD; 
$array1 = ['mp', 'tm', 'de', 'HK']; 
$array2 = ['MAP', 'TM', "DECIMAL", '字']; 

$hash = array_combine($array1, $array2); 
foreach($hash as $k => $v) { 
    $string = preg_replace_callback('/'.preg_quote($k).'(?=\s|$)/u', function($m) use($v) { 
     return $v; 
    }, 
    $string 
    ); 
} 
echo $string,"\n"; 

(?=\s|$)是在先行是確保我們有什麼樣的空間(即空格,製表符,回車,換行,...)或搜索後字符串的結尾ed密鑰。有了這個,我們保持白色空間不變。

/u是unicode標誌。

輸出:

sampleMAP okay DECIMAL  helloTM 
blaTM the字 end 
+0

謝謝你和這個向前看的解釋。我之前沒有聽說過預測,只是意識到它們對於其他情況會有多大用處!我還修改了我的原始代碼,現在它使用PDO :: FETCH_KEY_PAIR從數據庫中提取數據,這在我之前沒有聽說過。所以,應該希望使事情快一點,而不是使用array_combine。 – kojow7

+0

您的方法與Josh H提到的方法相比如何? – kojow7

+0

@ kojow7:我的答案是照着任何類型的空格('\ s')或單詞後面的結尾(''''),正如你所要求的那樣。喬希的回答是照顧一個字的邊界。 – Toto

1

你可以使用正則表達式來做到這一點。

首先轉換您的模式,以正則表達式和追加 '\ B' 到你的模式,這意味着字邊界(空格,製表,EOL ...):

foreach($array1 as $k => $v) { 
    $array1[$k] = '/'.$v.'\\b/'; 
} 

然後用了preg_replace替換:

$result = preg_replace($array1, $array2, "samplemp okay hellotm"); 
+0

這將在所有單詞的末尾替換它,而不僅僅是字符串的最後一個單詞。 – Barmar

+0

@Barmar我想要替換字符串中所有單詞的最後一個字符。 – kojow7

+0

@ kojow7您從發佈的代碼中看不清楚,因爲您從不將「$ mystring」分成單獨的單詞。 – Barmar

2

使用正向表達式,該向前表達式匹配字符串末尾的任何空白序列。

$array1 = ['/mp(?=\s*$)/', 'tm(?=\s*$)/', 'de(?=\s*$)/']; 
$array2 = ['MAP', 'TM', "DECIMAL"]; 

$newlast = preg_replace($array1, $array2, $last); 
+0

由於數組正在從數據庫填充並可能包含超過一百個項目,您是否建議我循環$ array1並將'/'和'(?= \ s * $)/'連接到每個項目數組? – kojow7

+0

是的,這就是如何動態地做到這一點。 – Barmar

2

未經測試,你可以做這樣的事情

$array2 = ['mp' => 'MAP', 'tm' => 'TM', 'de' => "DECIMAL"]; 

$mystring = "samplemp"; 
$patt = '/('.implode('|',array_keys($array2)) .')\b/'; 

$newlast = preg_replace_callback($patt , function($m) use ($array2){ 
    return $array2[$m[1]]; 
}, $mystring); 

echo "\n$newlast"; 

使用preg_replace_callback你能避免通過輸入數組,而是循環雖然比賽,這應該提供一些性能小幅上升循環,眼見在大多數情況下,會有更多的可能性(輸入),然後是實際匹配。

這個正則表達式的作品出來是這樣的:

/(mp|tm|de)\b/ 

所以,這將捕獲mptmde而只用一個字末突破\b,爲的結束字符串或單詞的結尾,因此它不會匹配dende例如。

回調部分是非常直接的,每當輸入字符串匹配時,回調被觸發,並且該匹配作爲第一個參數傳遞給該函數。比賽的格式就像preg_match的作品。然後,無論您返回什麼作爲替換字符串。這只是訪問數組中key =>值對的簡單方法。

use在閉包中只是一個範圍解析運算符,它允許您傳遞通常不在閉包範圍之外的變量。 '

這樣做的真正好處是,您不必爲模式使用循環來準備數組,只需對它進行內部處理即可。此外,它在匹配上循環,而不是在輸入上循環。大多數其他答案會做一個循環來準備模式,然後再循環模式。 「循環賽是不可避免的」,我說鬆散循環只是意味着重複的操作。

在任何情況下,你可以在這裏

https://regex101.com/r/AYw111/1

+0

謝謝你的回答。我很難完全理解你的代碼,因爲我不太熟悉回調。然而,沒有進一步的解釋,我不明白它是如何解釋和保留空白的。 – kojow7

+0

它沒有帳戶或保留空白,它忽略它。 '\ b'是一個單詞中斷或單詞的結尾,所以它是匹配的,數組鍵'|'pipe是一個或者,在一個單詞的結尾,並用該單詞的數組值替換它。 – ArtisticPhoenix

+0

preg_replace_callback,每次與匹配'$ m'匹配時觸發回調,'use'部分只允許'$ array'變量的作用域。 – ArtisticPhoenix

1

測試至REGx您可以分割字符串到數組,然後檢查特定的詞爲您更換。試試這個:

$array1 = ['mp', 'tm', 'de', 'HK']; 
$array2 = ['MAP', 'TM', "DECIMAL", '字']; 

$mystring = "samplemp \t okay hellotm"; 
preg_match_all('/\s+/', $mystring,$space_array); 
$space_array = isset($space_array[0])?$space_array[0]:$space_array; 
$test_array = preg_split('/\s+/', $mystring); 
$change_array= array(); 
$new_str = ""; 
foreach ($test_array as $key => $value) {   
    $last = substr($value, -2); 
    $newlast = str_replace($array1, $array2, $last); 
    if ($last != $newlast){ 
     $value = substr($value, 0, strlen($value)-2).$newlast; 
    } 
    $value .= isset($space_array[$key])?$space_array[$key]:""; 
    $change_array[] = $value;  
} 
var_dump(implode("", $change_array)); 
+0

感謝您的回答,但是,作爲我請求的一部分,它必須能夠考慮所有類型的空白,而不僅僅是空格。 – kojow7

+0

@ kojow7我編輯了我所有類型的空間的代碼。現在檢查它。 –

1

這裏有一個快速的功能,我敲在一起,應該做你需要的。它分割字符串,然後查找array1中的最後2個字母。如果它發現它,它將使用array2中的結束字母替換。如果它到達循環的結尾並且沒有返回,則返回原始字符串。

<?php 

function replaceString($string) 
{ 
    $array1 = ['mp', 'tm', 'de']; 
    $array2 = ['MAP', 'TM', "DECIMAL"]; 
    $first = substr($string, 0, -2); 
    $last = substr($string, -2); 
    $split = [ 
     'start' => $first, 
     'end' => $last, 
    ]; 
    foreach ($array1 as $key => $val) { 
     if ($val == $split['end']) { 
      $word = $split['start'].$array2[$key]; 
      return $word; 
     } 
    } 
    return $string; 
} 


echo replaceString("samplemp")."\n"; 
echo replaceString("okay")."\n"; 
echo replaceString("hellotm")."\n"; 

sampleMAP 好嗎 helloTM

活生生的例子這裏https://3v4l.org/fJCIY

+0

你似乎在這裏手動分割字符串。我需要保持原始空白完好的東西。 – kojow7

1

多去一些其他的答案已經在這裏稍微簡單:

$mystring = <<<EOD 
samplemp okay MADE de  hellotm 
blatm theHK end 
EOD; 
$array1 = ['mp', 'tm', 'de', 'HK']; 
$array2 = ['MAP', 'TM', "DECIMAL", '字']; 
foreach($array1 as $key=>$v){ 
    $mystring = preg_replace("/".preg_quote($v)."\b/u", $array2[$key], $mystring); 
} 
相關問題