2014-10-28 8 views
6

Próbuję utworzyć wspólne maski z ciągiem tak:Jak mogę zamienić wiele ciągów w łańcuchu bez nakładania się wyników?

012abc.d+e_fg~hijk => 012{start}.d+{middle}_fg~{end}jk 

wymienić:

$arrFromTo = array(
       'st' => '{pre}', 
       'abc' => '{start}', 
       'e' => '{middle}', 
       'hi' => '{end}', 
       'dd' => '{post}' 
      ); 

Zamiast Trzymam nakładających zamienniki i dostać coś takiego zamiast (za pomocą pętli str_replace ' e)

012{{pre}art}.d+{mi{post}le}_fg~{end}jk 

Ponieważ st znajduje się już zastąpiony {start} i dd znajduje się w {middle}.

Jak zastąpiłbyś poniższe?

$str = 'abc.d+e_fg~hijk'; 

echo replace_vars($str); // Desired output: 012{start}.d+{middle}_fg~{end}kJ 
+0

Zastanawiałem się nad uporządkowaniem tablicy, więc '' dd '=>' {post} ''znajdowało się w innej pozycji, ale wywoływało to inne problemy. –

+0

Nieczęsto proponuję regex, ale w tym przypadku może to być rozsądne, więc wykonuj uprzedzenia/tyły, aby sprawdzić, czego się spodziewasz, zanim zastąpisz –

+0

@scrowler Niestety w mojej bibliotece PCRE występuje błąd o ujemnej jakości wstecznej o zmiennej długości. Nie mogę uaktualnić biblioteki PCRE, więc w tym momencie przestałem iść tą ścieżką. – Ryan

Odpowiedz

6

Mogę źle zrozumieć, ale wydaje się, że nie potrzebujesz wyrażeń regularnych do zastąpienia. Są prostymi, dosłownymi zamiennikami.

$from = '012abc.d+e_fg~hijk'; 
$arrFromTo = array(
       'st' => '{pre}', 
       'abc' => '{start}', 
       'e' => '{middle}', 
       'hi' => '{end}', 
       'dd' => '{post}' 
      ); 
$to = strtr($from, $arrFromTo); // 012{start}.d+{middle}_fg~{end}jk 

strtr() jest niesamowity. Zajmuje bardzo czytelny sygnał wejściowy i nie zastępuje go ponownie w pętli.

2

Można użyć preg_replace takiego:

$str = '012abc.d+e_fg~hijk'; 
$arrFromTo = array(
       'st' => '{pre}', 
       'abc' => '{start}', 
       'e' => '{middle}', 
       'hi' => '{end}', 
       'dd' => '{post}' 
      ); 

$reArr=array(); 
foreach($arrFromTo as $k=>$v){ 
    $reArr['/' . $k . '(?![^{}]*})/'] = $v; 
} 

echo preg_replace(array_keys($reArr), array_values($reArr), $str); 
//=> 012{start}.d+{middle}_fg~{end}jk 

Rdzeń tego regex jest ta negatywna lookaead: (?![^{}]*})

Które uniknąć pasujące klucze tablicy, jeśli jest on zamknięty w {...} ponieważ wszystkie zamienniki są zawarte w {...}.

+0

Dlaczego 'preg_replace'? Dlaczego nie "str_replace" lub "strtr"? Nie jest konieczne wykonywanie wyreżyserowania, prawda? – Rudie

+0

Jak korzystać z wyprzedzającego w 'str_replace'? – anubhava

+1

Dlaczego potrzebujesz wyprzedzić? Są dosłownymi zamiennikami ... Nie ma żadnych '{' i '}' w łańcuchu źródłowym. – Rudie

0

Spowoduje to wyszukanie ciągu znaków dla każdego zamiennika w kolejności. Jeśli znajdzie, podzieli ciąg znaków i przeszuka pozostałą część ciągu w poszukiwaniu innych zamienników.

$str = '012abc.d+e_fg~hijk'; 

$rep = array(
    'st' => '{pre}', 
    'abc' => '{start}', 
    'e' => '{middle}', 
    'hi' => '{end}', 
    'dd' => '{post}' 
); 

$searched = ''; 

foreach ($rep as $key => $r) { 
    if (strpos($str, $key) !== false) { 

     $searched .= substr($str, 0, strpos($str, $key)) . $r; 
     $str = substr($str, strpos($str, $key) + strlen($key)); 

    } 
} 

$searched .= $str; 

echo $searched; //012{start}.d+{middle}_fg~{end}jk 

Przeszuka i znajdzie je w podanej kolejności.

Powiązane problemy