2015-07-22 62 views
1

我对PHP的preg_replace()函数有问题。为什么我会从preg_replace()函数获得不同的回报?

$string="[y-z]y-z_y[y_z]yav[v_v]"; // i want it to become : [y-z]yellow-zend_yellow[y_z]yav[v_v] 

$find = array('/y(?=(?:.(?!\]))*\[)/Um', '/a(?=(?:.(?!\]))*\[)/Um', '/z(?=(?:.(?!\]))*\[)/Um', '/v(?=(?:.(?!\]))*\[)/Um'); 

$replace = array('yellow', 'avocado', 'zend', 'vodka'); 

echo preg_replace($find, $replace, $string)."<br><br>"; // display [y-zend]yellow-zend_yellow[y_zend]yellowavodkaocadovodka[v_v] 

echo preg_replace('/y(?=(?:.(?!\]))*\[)/Um', 'yellow', $string)."<br><br>"; // display [y-z]yellow-z_yellow[y_z]yellowav[v_v] 

echo preg_replace('/z(?=(?:.(?!\]))*\[)/Um', 'zend', $string)."<br><br>"; // display [y-zend]y-zend_y[y_zend]yav[v_v] --Why displaying zend inside[]? 

另外,我想知道是否有一种方法有一个附加条件做这个简单的PHP:如果有“] [”之间的“YAV”字符串,我想忽略它。

**[y-z]y-z_y[y_z]yav[v_v] ==> [y-z]yellow-zend_yellow[y_z]yav[v_v]** 

OR

$var=[y-z]y-z[y_z]yav[v_v]; ==> $var=[y-z]yellow-zend[y_z]yav[v_v];

+0

你如何从'] ya'告诉''y-'在这里,我刚刚改变了你的生活大声笑,点击我> https:// regex101。com/ – ArtisticPhoenix

+0

do string_replace('y-z_y','yellow-zend_yellow','[y-z] y-z_y [y_z] yav [v_v]'); – ArtisticPhoenix

+0

@ArtisiticPhoenix不,不工作如果var是:[yz] yz [y_z] yav [v_v] ==> [yz] yellow-zend [y_z] yav [v_v]我需要一些东西来处理所有情况,使用大量内存并用特定字符串替换每个单词 – Mouad

回答

2

最后Z]匹配becase的你告诉它使用正展望未来匹配负面看,它基本上是一个矛盾的说法。

你告诉它匹配z如果lookahead匹配,而不匹配你不想要的,所以它匹配你不想要的,并说它确定匹配。无论如何,这在我的脑海中是有道理的。

https://regex101.com/r/nX5dQ6/1

您可以量化你的规则来匹配多个字符序列,它肯定更容易与yellow-zend_yellow取代y-z_y但没有上下文,这是不可能的说,如果这是可能的。

/z(?=(?:.(?!\]))*\[)/Um 
    z matches the character z literally (case sensitive) 
    (?=(?:.(?!\]))*\[) Positive Lookahead - Assert that the regex below can be matched 
     (?:.(?!\]))* Non-capturing group 
      Quantifier: * Between zero and unlimited times, as few times as possible, expanding as needed [lazy] 
      . matches any character (except newline) 
      (?!\]) Negative Lookahead - Assert that it is impossible to match the regex below 
       \] matches the character ] literally 
     \[ matches the character [ literally 
    U modifier: Ungreedy. The match becomes lazy by default. Now a ? following a quantifier makes it greedy 
    m modifier: multi-line. Causes^and $ to match the begin/end of each line (not only begin/end of string) 

个人我可能会做一个标记生成器它的想法是preg_match_all改为使用,这样

$matches = null; 
$returnValue = preg_match_all('/(?P<T_OPEN>\[)|(?P<T_CLOSE>\])|(?P<T_Y>y)|(?P<T_X>x)|(?P<T_Z>z)|(?P<T_SEPH>\-)|(?P<T_SEPU>\_)/', '[y-z]y-z_y[y_z]yav[v_v]', $matches, PREG_PATTERN_ORDER); 

返回

array (
    0 => 
     array (
       0 => '[', 
       1 => 'y', 
       2 => '-', 
       3 => 'z', 
       4 => ']', 
      ... 
     ), 
    'T_OPEN' => 
     array (
      0 => '[', 
      1 => '', 
      2 => '', 
      3 => '', 
      4 => '', 
    .. 

并与一些后处理这可以简化成一个令牌列表

array('T_OPEN', 'T_Y', 'T_SEPH', 'T_Z', 'T_CLOSE', ...); 

哪些是命名的捕获组,那么这是很平凡的,如果你是[],或不含在写一些逻辑来确定,或者如果T_Y,T_X,T_Z是之前由另一T_Y,T_X, T_Z令牌,这是最​​可靠的方法。

处理它下降到只有令牌上的[0] [0]比赛使用一个for循环,看看别人有这样的值(未测试,但是这是它的基础)

$total = count($matches[0][0]); 
    // remove numbered keys this is just an array of all the string keys, our tokens 
$tokens = array_filter(function($item){ 
     return preg_match('/^[^0-9]/', $item); 
}, array_keys($matches)); 
$tokens[] = 'T_UNKNOWN'; //add a default token for validation 

$tokenstream = array(); 
for($i=0; $i<$total; $i++){ 
    //loop through the matches for the index, 
     foreach($tokens as $token){ 
      //loop through the tokens and check $matches[$token][$i] for length 
      if(strlen($matches[$token][$i]) > 0){ 
        break; //break out of the foreach when we find our token which is now in $token - if we don't find it it's the last token T_UNKNOWN 
      } 
      } 
     $tokenstream[] = $token; 
} 

然后你从头开始使用令牌建立自己的字符串,

$out = ''; 
$literal = false; 

    foreach($tokenstream as $offset => $token){ 
     switch($token){ 
      case 'T_OPEN': 
        $out .= '['; 
        $literal = true; //start brackets 
      break; 
      case 'T_CLOSE': 
        $out .= ']'; 
        $literal = false; //end brackets 
      break; 
      case 'T_SEPH': 
        $out .= '-'; 
      break; 
      case 'T_Y': 
        if($literal){ //if inside brackets literal y 
         $out .= 'y'; 
        }else{ // else use the word yellow 
         $out .= 'yellow'; 
        } 
      break; 
      case 'T_UNKNOWN': 
        //validate 
        throw new Exception("Error unknown token at offset: $offset"); 

     } 
    } 

你还是会需要弄清楚的T_Z后跟一个T_A,等等,等等,但是这将是一个肯定火的方式做它,并避免以上所有的混乱。此外,这是一个非常粗糙的思考这样的问题的方式。

+0

不,先生,如果我有:$ var = [y-z] y-z [y_z] yav [v_v]; ==> $ var = [y-z] yellow-zend [y_z] yav [v_v] ;.以及如何在字符串中输入单词yav – Mouad

+0

我应该怎么知道,这是你的问题,什么是一些样本输入,一个输入不足以解决这个问题。有很多方法可以做到这一点,你可以使用[y-z]组preg_split等。 – ArtisticPhoenix

+0

谢谢,这是非常接近我的旧解决方案与数组,循环和开关,但它需要大量变量的内存。因为这个原因,我认为如果我使用替换函数的简单方法,我减少了一些内存使用量,但似乎不可能。顺便说一下,我需要这样做一些HTML enc0ding我加载大量的HTML源到内存工作。以编码

p

为例:<%70>&#%78%37%30;我需要用不同的值替换单词和单词之间的单词。感谢您的意见我非常感谢^^' – Mouad

相关问题