有没有办法使用正则表达式替换基于位置的字符串中的字符?
例如,我正在处理的项目的重写规则之一是“如果o
是倒数第二个元音,则将ö
替换为o
,甚至编号(从左到右计数)。“
所以,例如:
heabatoik
将成为heabatöik
(o
是倒数第二个元音,以及第四个元音)habatoik
不会改变(o
是倒数第二个元音,但是是第三个元音)这可以在PHP中使用preg_replace
吗?
答案 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);
}