2

例如,下面的代码用<i>标签包装每个匹配的字符。

echo preg_replace('/[aeiou]/', '<i>$0</i>', 'alphabet');
// result: <i>a</i>lph<i>a</i>b<i>e</i>t

但我希望它只替换每个字符一次。

我正在寻找类似的结果<i>a</i>lphab<i>e</i>t,第二个a在没有标签的情况下通过,因为搜索字符串只有一个a

你能帮我吗?如果不遍历 foreach 循环中的每个字符,这是否可能?

答案还应该允许两个或多个相同的字符,每个字符只能使用一次。例如,如果我aaeioo在 string中搜索alphabetsoupisgood,它应该匹配两个a's 但只有三个o's 中的两个。

4

6 回答 6

3

如果您只想替换一个字母一次,那么下面的正则表达式应该可以工作:

echo preg_replace('/([aeiou])(?!.+?\\1)/', '<i>$1</i>', 'alphabet');

输出:

alph<i>a</i>b<i>e</i>t

PS:请注意,它替换了最后一个字母而不是第一个字母。

编辑:

以下将产生与 OP 预期相同的输出(感谢@AntonyHatchkins):

echo strrev(preg_replace
        ('/([aeiou])(?!.+?\\1)/', strrev('<i>1$</i>'), strrev('alphabet')))."\n";

编辑2:

根据OP的评论:

Can you help me allow more than one a then? How can I match 2, but not 3 a's

我发布这个答案:

echo strrev(preg_replace('/([aeiou])(?!(.+?\\1){2})/', 
            strrev('<i>1$</i>'), strrev('alphabetax'))) . "\n";

编辑 3:

根据OP的另一条评论:

that will allow duplicates for all characters in the string, not just 2 a's & 1 e

我发布这个答案:

echo strrev(preg_replace(array('/(a)(?!(.+?\\1){2})/', 
  '/(?<!>)([eiou])(?!.+?\\1)/'), 
  array(strrev('<i>1$</i>'), strrev('<i>1$</i>')), strrev('alphabetaxen')))."\n";

输出:

<i>a</i>lph<i>a</i>b<i>e</i>taxen

注意:我相信原始问题已经改变了很多次,所以请不要在这个问题中增加进一步的复杂性。如果您有不同的疑问,您可以自由发布另一个问题。

于 2012-10-30T04:33:14.500 回答
0

根据http://php.net/manual/es/function.preg-replace.php,您可以指定一个附加参数来限制完成的替换数量。

编辑:对不起,我最初没有得到你的问题。在这种情况下,这是不可能的。由于正则表达式的性质,它不知道它已经进行了多少替换。虽然我可能是错的,但我怀疑是否存在一个只对每个字符进行一次替换的正则表达式。

你最好的选择是打 5 个电话,每个字符一个。像这样的东西:

$res = preg_replace('/a/', '<i>$0</i>', 'alphabet', 1);
$res = preg_replace('/e/', '<i>$0</i>', 'alphabet', 1);
$res = preg_replace('/i/', '<i>$0</i>', 'alphabet', 1);
$res = preg_replace('/o/', '<i>$0</i>', 'alphabet', 1);
$res = preg_replace('/u/', '<i>$0</i>', 'alphabet', 1);

echo $res;

干杯

于 2012-10-30T04:07:31.507 回答
0

采用

echo preg_replace('/[aeiou]/', ' ', 'alphabet', 1); 

抱歉,在您编辑问题之前我已回答

这个怎么样。

$word = "alphabet";

$replace = array('a','e','i','o','u');
$with = array('','','','','');

echo str_replace($replace,$with,$word); //lphbt
于 2012-10-30T04:13:06.013 回答
0

丑陋,但这是一种方法。

echo 
preg_replace('/a/','<i>$0</i>',
preg_replace('/e/','<i>$0</i>',
preg_replace('/i/','<i>$0</i>',
preg_replace('/o/','<i>$0</i>',
preg_replace('/u/','<i>$0</i>','alphabet',
1),1),1),1),1);
于 2012-10-30T04:19:00.167 回答
0

这是使用该功能的另一种方法,preg_replace_callback()因此我将其发布为全新的答案。

function replace_first($matches) {
    static $used = array();
    $key = $matches[0];
    if (in_array($key,$used)) return $key;
    $used[] = $key;
    return '<i>' . $key . '</i>';
}

$str = preg_replace_callback('/[aeiou]/','replace_first','alphabet');
echo $str;

将输出<i>a</i>lphab<i>e</i>t

于 2012-10-30T04:46:26.737 回答
-1

我能做的最好的就是循环遍历每个字符。(我尽量避免循环)我希望有一种更清洁的方法,但现在就可以了。

$word = 'alphabetsoupisgood';
$match = 'aaeou';
$wordArr = str_split($word);
$matchArr = str_split($capitals);

foreach ($matchArr as $c) {
    $key = array_search($c, $wordArr);
    if ($key !== false) {
        $wordArr[$key] = strtoupper($c);
    }
}

foreach ($wordArr as $k => $c) {
    if (ctype_upper($c)) {
        $wordArr[$k] = '<i>' . strtolower($c) . '</i>';
    }
}
$word = implode('',$wordArr);
echo $word;

它在键盘中,但他们正在运行一些超级旧版本的 PHP,因此ctype_upper未启用... http://codepad.org/UoLWcK2S

如果有人可以使用 preg_replace 提供更清晰的答案,我很乐意将您的答案标记为答案。

于 2012-10-30T13:22:12.320 回答