Dizesindeki konumuna dayalı Değiştirilmesi (Regex)

4 Cevap php

Konumuna dayalı bir dizeden karakterleri değiştirmek için regex kullanarak bir yolu var mı?

Örneğin, ben üzerinde çalışıyorum bir proje için benim yeniden yazma kurallarından biri o bile son ünlüsü yanında ise "ö ile o değiştirin sayılı "(soldan sağa sayma)

Yani, bir örnek:

heabatoik heabatöik (o en son bir sesli harf için bir sonraki, hem de 4 ünlü olan) olacak

habatoik değişiklik olmaz (o son ünlüsü yanında, ama 3 ünlü olan)

Bu preg_replace PHP kullanılarak mümkün mü?

4 Cevap

Konusu dizenin başından başlayarak, 2 n + bir o, ardından 1 ünlüler, ama o tam olarak takip yalnızca maç istiyorum bir daha ünlü:

$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');

Aynı yapmak ama tek sayılı bir o, maç 2 n yerine 2'den ünlüleri gelen n + 1 için için:

$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');

Biri uymazsa, o zaman hiçbir değişimini gerçekleştirir, bu yüzden bunu yapmak için çalışıyoruz buysa sırayla onları çalıştırmak için güvenlidir.

Sen preg_match_all sesli / non-sesli bölüme dize bölmek ve bu işlemek için kullanabilirsiniz.

örneğin gibi bir şey

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

Özel ihtiyaçlarına bağlı olarak, regex ()*+? yerleştirme değiştirmeniz gerekebilir.

Ben Schmitt genişletmek istiyorum. (Bir yorum eklemek için yeterli puan yok, ben onun gök çalmak için çalışıyorum değilim). Bu ünlüleri değil, aynı zamanda orada yerleri sadece döner gibi ben bayrağı PREG_OFFSET_CAPTURE kullanmak istiyorsunuz. Bu benim çözümdür:

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]);

not:

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
                )
        )
)

Bu ben bunu nasıl olduğunu:

$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);
}