2

たとえば、次のコードは、一致する各文字を<i>タグでラップします。

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

しかし、各キャラクターを一度だけ置き換えたいと思います。

のような結果を探しています。検索文字列には が 1 つしかないため<i>a</i>lphab<i>e</i>t、2 番目aはタグなしで通過しますa

手伝ってくれますか?これは、foreach ループで各文字を反復せずに可能ですか?

回答では、同じ文字を 2 つ以上使用できるようにし、それぞれを 1 回だけ使用できるようにする必要があります。たとえばaaeioo、文字列alphabetsoupisgoodで を検索した場合、両方の に一致する必要がありますaが、3 つoの のうちの 2 つのみに一致する必要があります。

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によると、置換の量を制限する追加のパラメーターを指定できます。

編集:申し訳ありませんが、最初はあなたの質問を受け取りませんでした。その場合、それは不可能です。正規表現の性質上、行った置換の量は認識されません。私は間違っているかもしれませんが、文字ごとに 1 つの置換のみを行う正規表現が存在するとは思えません。

あなたの最善の策は、キャラクターごとに1つずつ、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

これは関数を使用した別のアプローチ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 に答える
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

使用する

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 に答える
-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 に答える