2010-08-15 16 views
6

मैं यह सुनिश्चित करना चाहता हूं कि कुछ स्ट्रिंग प्रतिस्थापन जो मैं चल रहा हूं वह बहु बाइट सुरक्षित है। मुझे नेट के चारों ओर कुछ mb_str_replace फ़ंक्शंस मिले हैं लेकिन वे धीमे हैं। मैं इसके माध्यम से 500-900 बाइट पारित करने के बाद 20% की वृद्धि कर रहा हूं।mb_str_replace() ... धीमा है। कोई विकल्प?

कोई सिफारिशें? मैं preg_replace का उपयोग करने के बारे में सोच रहा हूं क्योंकि यह मूल है और संकलित है ताकि यह तेज़ हो सके। किसी भी विचार की सराहना की जाएगी।

+0

आप और अधिक जानकारी देने के लिए की जरूरत है। प्रतिस्थापन स्ट्रिंग और विषय के एन्कोडिंग क्या है? यदि विषय यूटीएफ -8 है और प्रतिस्थापन स्ट्रिंग ASCII रेंज में है, तो आप 'str_replace' का उपयोग कर सकते हैं। – Artefacto

+0

यूनिकोड के आसपास रहा है, क्या, 15 साल अब? अभी भी एक कोर आंतरिक पाश में एमबी तारों के साथ mucking? अंदर से काम करते हैं। –

उत्तर

10

जैसा कि there कहा गया है, str_replace utf-8 संदर्भों में उपयोग करने के लिए सुरक्षित है, जब तक कि सभी पैरामीटर utf-8 मान्य हैं, क्योंकि यह मल्टीबाइट एन्कोडेड स्ट्रिंग्स दोनों के बीच कोई अस्पष्ट मिलान नहीं होगा। यदि आप अपने इनपुट की वैधता की जांच करते हैं, तो आपको एक अलग फ़ंक्शन देखने की आवश्यकता नहीं है।

+3

यह गलत है यदि आप यूनिकोड के साथ काम कर रहे हैं और [यूनिकोड समतुल्यता] (http://en.wikipedia.org/wiki/Unicode_equivalence) के बारे में परवाह करते हैं। यूनिकोड में कई अलग-अलग बाइट अनुक्रम एक ही चरित्र का प्रतिनिधित्व कर सकते हैं। 'Str_replace' का उपयोग करना ** केवल ** काम करेगा यदि आप पहले अपने तारों को सामान्य करते हैं। – Qtax

+0

अच्छी टिप, वैसे भी मेरी समझ "मल्टीबाइट सुरक्षित" है, "वे मिलान करते समय कोई झूठी सकारात्मक नहीं देंगे", अभ्यास में क्या मतलब है कि वे प्रतिस्थापन के लिए वांछित चीज़ों के संदर्भ में आउटपुट जानकारी को भ्रष्ट नहीं करेंगे। –

+0

प्रदान की गई लिंक की जांच करें – Trix

3

एन्कोडिंग एक असली चुनौती है जब हर जगह से इनपुट (utf8 या अन्य) हैं, मैं केवल मल्टीबाइट-सुरक्षित फ़ंक्शंस का उपयोग करना पसंद करता हूं। str_replace के लिए, मैं this one का उपयोग कर रहा हूं जो कि पर्याप्त तेज़ है।

if (!function_exists('mb_str_replace')) 
{ 
    function mb_str_replace($search, $replace, $subject, &$count = 0) 
    { 
     if (!is_array($subject)) 
     { 
     $searches = is_array($search) ? array_values($search) : array($search); 
     $replacements = is_array($replace) ? array_values($replace) : array($replace); 
     $replacements = array_pad($replacements, count($searches), ''); 
     foreach ($searches as $key => $search) 
     { 
      $parts = mb_split(preg_quote($search), $subject); 
      $count += count($parts) - 1; 
      $subject = implode($replacements[$key], $parts); 
     } 
     } 
     else 
     { 
     foreach ($subject as $key => $value) 
     { 
      $subject[$key] = mb_str_replace($search, $replace, $value, $count); 
     } 
     } 
     return $subject; 
    } 
} 
2

यहाँ मेरी कार्यान्वयन, Alain's answer बंद आधारित है:

/** 
* Replace all occurrences of the search string with the replacement string. Multibyte safe. 
* 
* @param string|array $search The value being searched for, otherwise known as the needle. An array may be used to designate multiple needles. 
* @param string|array $replace The replacement value that replaces found search values. An array may be used to designate multiple replacements. 
* @param string|array $subject The string or array being searched and replaced on, otherwise known as the haystack. 
*        If subject is an array, then the search and replace is performed with every entry of subject, and the return value is an array as well. 
* @param string $encoding The encoding parameter is the character encoding. If it is omitted, the internal character encoding value will be used. 
* @param int $count If passed, this will be set to the number of replacements performed. 
* @return array|string 
*/ 
public static function mbReplace($search, $replace, $subject, $encoding = 'auto', &$count=0) { 
    if(!is_array($subject)) { 
     $searches = is_array($search) ? array_values($search) : [$search]; 
     $replacements = is_array($replace) ? array_values($replace) : [$replace]; 
     $replacements = array_pad($replacements, count($searches), ''); 
     foreach($searches as $key => $search) { 
      $replace = $replacements[$key]; 
      $search_len = mb_strlen($search, $encoding); 

      $sb = []; 
      while(($offset = mb_strpos($subject, $search, 0, $encoding)) !== false) { 
       $sb[] = mb_substr($subject, 0, $offset, $encoding); 
       $subject = mb_substr($subject, $offset + $search_len, null, $encoding); 
       ++$count; 
      } 
      $sb[] = $subject; 
      $subject = implode($replace, $sb); 
     } 
    } else { 
     foreach($subject as $key => $value) { 
      $subject[$key] = self::mbReplace($search, $replace, $value, $encoding, $count); 
     } 
    } 
    return $subject; 
} 

उनकी एक वर्ण एन्कोडिंग को स्वीकार नहीं करता है, हालांकि मैं तुम्हें mb_regex_encoding के माध्यम से यह निर्धारित कर सकते हैं लगता है।

मेरे इकाई परीक्षण पास:

function testMbReplace() { 
    $this->assertSame('bbb',Str::mbReplace('a','b','aaa','auto',$count1)); 
    $this->assertSame(3,$count1); 
    $this->assertSame('ccc',Str::mbReplace(['a','b'],['b','c'],'aaa','auto',$count2)); 
    $this->assertSame(6,$count2); 
    $this->assertSame("\xbf\x5c\x27",Str::mbReplace("\x27","\x5c\x27","\xbf\x27",'iso-8859-1')); 
    $this->assertSame("\xbf\x27",Str::mbReplace("\x27","\x5c\x27","\xbf\x27",'gbk')); 
} 
संबंधित मुद्दे