2016-06-22 2 views
2

То, что я пытаюсь сделать, это найти вопросительные знаки в строке и заменить ее на &, кроме первого. Мой код до сих пор:Как заменить появление символа в строке, кроме первой

$str = 'www.domain.com?adult=2&airport=40-48?destination=recko';   
    echo preg_replace(array('/[?]/'), '&', $str); 

выход:

www.domain.com&adult=2&airport=40-48&destination=recko 

Как я могу игнорировать первое вхождение в ??

ответ

4

Match начала строки до первой ? и использовать (*SKIP)(*F) пропустить первый матч:

$str = 'www.domain.com?adult=2&airport=40-48?destination=recko';   
echo preg_replace('/^[^?]*\?(*SKIP)(*F)|[?]/', '&', $str); 
// => www.domain.com?adult=2&airport=40-48&destination=recko 

См детализирует IDEONE demo

Pattern:

  • ^ - начало строки
  • [^?]* - кроме 0+ символов ? как можно больше
  • \? - буквальный ?
  • (*SKIP)(*F) - два PCRE глаголов делает движок регулярных выражений опустить текст, совпадающий до сих пор в текущей итерации
  • | - или
  • [?] - буквальный ?

Альтернативы (*SKIP)(*FAIL) является использование preg_replace_callback и бывший шаблон с первой альтернативной ветвью внутри сохраняющих круглых скобок:

$str = 'www.domain.com?adult=2&airport=40-48?destination=recko';   
echo preg_replace_callback('/^([^?]*[?])|[?]/', function($m) { 
    return !empty($m[1]) ? $m[1] : "&"; 
}, $str); 

См this IDEONE demo

^([^?]*[?]) часть соответствует части строки с самого начала будет первыми ? и помещается в группу 1. Внутри анонимного метода, где мы передаем объект соответствия ($m), мы можем проверить, соответствует ли группа («участвовала в матче») с помощью !empty($m[1]). Если да, мы просто вернем его обратно. Если нет, то [?], вторая ветка соответствует, поэтому мы ее заменим.

+1

Именно то, что я искал. Спасибо – Roman

+0

очень хорошее объяснение – Roman

+0

Если вы хотите, вы можете прочитать больше на ['* (SKIP) (* FAIL)' здесь] (http://stackoverflow.com/questions/24534782/how-do-skip-or- е-работа-на-регулярное выражение) –

0

Не знаю, если это чистый способ, но будет работать, и это легко:

echo substr($str,0,1) . preg_replace(array('/[?]/'), '&', substr($str,1)); 
1

Мы просто цикл думал всю строку, чтобы найти первый? и замените друг на друга &. Нет необходимости использовать регулярное выражение, которое медленно

<?php 
$str = 'www.domain.com?adult=2&airport=40-48?destination=recko';  

$strlen = strlen($str); 
$passed_first = false; 

for($i = 0; $i < $strlen; $i++) { 
    if($str[$i] == "?") { 
     if(!$passed_first) { 
      $passed_first = true; 
     } else { 
      $str[$i] = "&"; 
     } 
    } 
} 

echo $str; 
0

Лучше всего было бы, я думаю, что это сделать explode("?",$str) или explode("&",$str) и поместить их в массив и сделать preg_replace() с малым, если состояние, когда вы берете первый ? и отдых вы игнорируете и сделать array_marge().

попробовать и дайте мне знать

0

Смотрите документацию по parse_url

С этим вы можете легко извлечь части URL и сделать строку заменить только на компоненте, который вас интересует

<?php 

$str = 'www.domain.com?adult=2&airport=40-48?destination=recko'; 

$url = parse_url($str); 
$url['query'] = str_replace('?', '&', $url['query']); 

echo $url['path'] . '?' . $url['query']; 
0

Вы можете использовать lookbehind вместе с \K

$str = preg_replace('/(?<=\?)[^?]*\K\?/', "&", $str); 

Внешний вид используется для запроса ? перед тем, который должен быть сопоставлен. [^?] соответствует любому символу, который не является ? (negated character class). \K сбрасывает начало сообщенного матча.

Demo at regex101 или PHP demo at eval.in


Или с помощью capturing group вместо \K: (?<=\?)([^?]*)\? and replace with $1&

Смежные вопросы