2010-02-01 59 views
7

有沒有使用正則表達式來替換字符串中基於位置的字符的方法?根據字符串中的位置進行替換

例如,對於一個項目,我的工作我的重寫規則之一是「與ö取代o如果o是下一個到最後一個元音和偶數(算上從左至右)。」

因此,例如:

  • heabatoik將成爲heabatöiko是下一個到最後一個元音,還有第四個元音)
  • habatoik不會改變(o是下一個到最後一個元音,但第三個元音)

這可能在PHP中使用preg_replace

回答

8

與主題字符串的開頭開始,你想匹配2個ň + 1元音後面是o,但前提是o後跟正好多一個元音:

$str = preg_replace(
    '/^((?:(?:[^aeiou]*[aeiou]){2})*)' . # 2n vowels, n >= 0 
    '([^aeiou]*[aeiou][^aeiou]*)' .  # odd-numbered vowel 
    'o' .        # even-numbered vowel is o 
    '(?=[^aeiou]*[aeiou][^aeiou]*$)/', # exactly one more vowel 
    '$1$2ö', 
    'heaeafesebatoik'); 

要做相同的,但對奇數o,匹配2個ñ領先元音,而不是2 ñ + 1:

$str = preg_replace(
    '/^((?:(?:[^aeiou]*[aeiou]){2})*)' . # 2n vowels, n >= 0 
    '([^aeiou]*)' .      # followed by non-vowels 
    'o' .        # odd-numbered vowel is o 
    '(?=[^aeiou]*[aeiou][^aeiou]*$)/', # exactly one more vowel 
    '$1$2ö', 
    'habatoik'); 

如果一個不匹配,那麼它不會執行替換,因此如果這是您正在嘗試執行的操作,則依次運行它們是安全的。

+1

爲什麼一個'+'在去年'[^ aeiou]同時+'而不是'*'? – 2010-02-01 16:10:29

+0

@巴特好抓! – 2010-02-01 16:12:51

+0

我認爲*我*看了一些東西! :) – 2010-02-01 16:16:19

1

您可以使用preg_match_all將字符串拆分爲元音/非元音部分並對其進行處理。

例如像

preg_match_all("/(([aeiou])|([^aeiou]+)*/", 
    $in, 
    $out, PREG_PATTERN_ORDER); 

根據您的具體需求,您可能需要修改的正則表達式的()*+?位置。

1

我喜歡在施密特上進行擴展。 (我沒有足夠的積分來添加評論,我沒有試圖竊取他的雷霆)。我會使用國旗PREG_OFFSET_CAPTURE,因爲它不僅返回元音,而且還返回位置。這是我的解決方案:

const LETTER = 1; 
const LOCATION = 2 
$string = 'heabatoik' 

preg_match_all('/[aeiou]/', $string, $in, $out, PREG_OFFSET_CAPTURE); 

$lastElement = count($out) - 1; // -1 for last element index based 0 

//if second last letter location is even 
//and second last letter is beside last letter 
if ($out[$lastElement - 1][LOCATION] % 2 == 0 && 
    $out[$lastElement - 1][LOCATION] + 1 == $out[$lastElement][LOCATION]) 
     substr_replace($string, 'ö', $out[$lastElement - 1][LOCATION]); 

注:

print_r(preg_match_all('/[aeiou]/', 'heabatoik', $in, $out, PREG_OFFSET_CAPTURE)); 
Array 
(
    [0] => Array 
     (
      [0] => Array 
       (
        [0] => e 
        [1] => 1 
       ) 

      [1] => Array 
       (
        [0] => a 
        [1] => 2 
       ) 

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

      [3] => Array 
       (
        [0] => o 
        [1] => 6 
       ) 

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

這是我會怎麼做:

$str = 'heabatoik'; 

$vowels = preg_replace('#[^aeiou]+#i', '', $str); 
$length = strlen($vowels); 
if ($length % 2 && $vowels[$length - 2] == 'o') { 
    $str = preg_replace('#o([^o]+)$#', 'ö$1', $str); 
}