2010-02-02 11 views
8

मैं preg_match_all('/[aäeëioöuáéíóú]/u', $in, $out, PREG_OFFSET_CAPTURE);UTF-8 preg_match_all (PHP) में पात्रों

तो $in = 'hëllo'$out है:

array(1) { 
[0]=> 
    array(2) { 
    [0]=> 
    array(2) { 
     [0]=> 
     string(2) "ë" 
    [1]=> 
    int(1) 
} 
[1]=> 
array(2) { 
    [0]=> 
    string(1) "o" 
    [1]=> 
    int(5) 
    } 
} 
} 

o की स्थिति 4. होना चाहिए मैं ऑनलाइन इस समस्या के बारे में पढ़ा है (ë 2 के रूप में गिना जाता है)। क्या इसका कोई समाधान है? मैंने mb_substr और इसी तरह देखा है, लेकिन preg_match_all के लिए ऐसा कुछ है?

संबंधित प्रकार: क्या वे पाइथन में preg_match_all के बराबर हैं? (स्ट्रिंग में अपनी स्थिति के साथ मैचों की एक सरणी लौटाना)

+1

आप एक अलग सवाल में है कि आप से पूछना चाहिए, लेकिन हाँ ... एक अजगर regex matchobject डिफ़ॉल्ट mo.start द्वारा मैच स्थिति (होते हैं) और mo.end() –

उत्तर

0

PHP यूनिकोड का बहुत अच्छा समर्थन नहीं करता है, इसलिए preg_ * सहित कई स्ट्रिंग फ़ंक्शंस अभी भी वर्णों के बजाय बाइट्स को गिनते हैं।

मैंने एन्कोडिंग और डिकोडिंग स्ट्रिंग द्वारा समाधान खोजने का प्रयास किया, लेकिन आखिरकार यह सब preg_match_all फ़ंक्शन पर आ गया।

पाइथन चीज़ के बारे में: एक अजगर रेगेक्स matchobject डिफ़ॉल्ट mo.start() और mo.end() द्वारा मिलान स्थिति शामिल है। देखें: http://docs.python.org/library/re.html#finding-all-adverbs-and-their-positions

+0

स्पष्ट रूप से इसे PHP6 में तय करने की योजना बनाई गई थी, लेकिन अभी तक 2016 तक (6 साल बाद) यह अभी भी चर्चा में है। प्यार PHP डेवलपर्स होना चाहिए। उनके पास कोई वास्तविक सुराग नहीं है। –

6

यह एक बग नहीं है, PREG_OFFSET_CAPTURE स्ट्रिंग में वर्ण के बाइट ऑफसेट को संदर्भित करता है।

mb_ereg_search_pos वैसे ही व्यवहार करता है। एक संभावना यह पहले UTF-32 के लिए एन्कोडिंग बदलने के लिए और फिर 4 से स्थिति को विभाजित (क्योंकि सभी यूनिकोड कोड इकाइयों UTF-32 में 4 बाइट दृश्यों के रूप में प्रतिनिधित्व कर रहे हैं) है:

mb_regex_encoding("UTF-32"); 
$string = mb_convert_encoding('hëllo', "UTF-32", "UTF-8"); 
$regex = mb_convert_encoding('[aäeëioöuáéíóú]', "UTF-32", "UTF-8"); 
mb_ereg_search_init ($string, $regex); 
$positions = array(); 
while ($r = mb_ereg_search_pos()) { 
    $positions[] = reset($r)/4; 
} 
print_r($positions); 

देता है:

 
Array 
(
    [0] => 1 
    [1] => 4 
) 

आप बाइनरी पदों को कोड इकाई पदों में भी परिवर्तित कर सकते हैं। UTF-8 के लिए, एक से इनकी दिया गया है:

function utf8_byte_offset_to_unit($string, $boff) { 
    $result = 0; 
    for ($i = 0; $i < $boff;) { 
     $result++; 
     $byte = $string[$i]; 
     $base2 = str_pad(
      base_convert((string) ord($byte), 10, 2), 8, "0", STR_PAD_LEFT); 
     $p = strpos($base2, "0"); 
     if ($p == 0) { $i++; } 
     elseif ($p <= 4) { $i += $p; } 
     else { return FALSE; } 
    } 
    return $result; 
} 
2

वहाँ, सरल समाधान नहीं है preg_match के बाद इस्तेमाल किया जाएगा() परिणाम मेल नहीं खाते। आप निम्न के साथ हर मैच परिणाम पुनरावृति और स्थिति मूल्य पुन: असाइन करने की जरूरत है:

$utfPosition = mb_strlen(substr($wholeSubjectString, 0, $capturedEntryPosition), 'utf-8'); 

Windows के तहत php 5.4 पर परीक्षण किया गया, multibyte PHP एक्सटेंशन केवल पर निर्भर करता है।

0

नियमित अभिव्यक्ति द्वारा यूटीएफ -8 $string को विभाजित करने का एक और तरीका है preg_split() फ़ंक्शन का उपयोग करना। यहाँ मेरे कार्य हल है:

$result = preg_split('~\[img/\d{1,}/img\]\s?~', $string, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE); 

पीएचपी 5.3.17

संबंधित मुद्दे