根据字符串中的位置替换

时间:2010-02-01 15:49:54

标签: php regex

有没有办法使用正则表达式替换基于位置的字符串中的字符?

例如,我正在处理的项目的重写规则之一是“如果o是倒数第二个元音,则将ö替换为o,甚至编号(从左到右计数)。“

所以,例如:

  • heabatoik将成为heabatöiko是倒数第二个元音,以及第四个元音)
  • habatoik不会改变(o是倒数第二个元音,但是是第三个元音)

这可以在PHP中使用preg_replace吗?

4 个答案:

答案 0 :(得分:8)

从主题字符串的开头开始,您希望匹配2 n + 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

要做同样的事情,但对于奇数编号$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'); ,匹配2 n 前导元音而不是2 n + 1:

{{1}}

如果一个不匹配,那么它不执行替换,因此如果您正在尝试这样做,则可以安全地按顺序运行它们。

答案 1 :(得分:1)

您可以使用preg_match_all将字符串拆分为元音/非元音部分并进行处理。

e.g。

之类的东西
preg_match_all("/(([aeiou])|([^aeiou]+)*/",
    $in,
    $out, PREG_PATTERN_ORDER);

根据您的具体需求,您可能需要修改正则表达式中()*+?的展示位置。

答案 2 :(得分: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
                )
        )
)

答案 3 :(得分: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);
}