代码之家  ›  专栏  ›  技术社区  ›  raveren

从regexp中获取比括号更多的反向引用

  •  1
  • raveren  · 技术社区  · 16 年前

    这很难用英语解释,所以我只举个例子。

    我将使用以下格式的字符串:

    key-value;key1-value;key2-...
    

    我需要将数据提取成一个数组

    array('key'=>'value','key1'=>'value1', ... )
    

    /^(\w+)-([^-;]+)(?:;(\w+)-([^-;]+))*;?$/
    

    合作 preg_match

    for ($l = count($matches),$i = 1;$i<$l;$i+=2) {
        $parameters[$matches[$i]] = $matches[$i+1];
    }
    

    然而,regexp显然只返回4个反向引用——输入字符串的第一个和最后一个键值对。有办法解决这个问题吗?我知道我可以使用正则表达式来测试字符串的正确性,并使用PHP的 explode 在循环中有完美的结果,但我真的很好奇正则表达式是否有可能。

    简而言之,我需要捕获任意数量的这些 key-value; 通过正则表达式在字符串中对。

    6 回复  |  直到 16 年前
        1
  •  2
  •   Alan Moore Chris Ballance    16 年前

    /\G(?=(?:\w++-[^;-]++;?)++$)(\w++)-([^;-]++);?/
    

    (?=(?:\w++-[^;-]++;?)++$) 这是验证部分。如果输入无效,匹配将立即失败,但每次应用正则表达式时仍会计算先行。为了使它(以及正则表达式的其余部分)与键值对保持同步,我使用 \G 将每场比赛锚定到上一场比赛结束的地点。

    这样,如果前瞻第一次成功,则保证以后每次都会成功。很明显,它的效率不如它可能的那么高,但这可能不会是一个问题——只有您的测试才能确定。

    preg_match_all() 将返回零(false)。如果成功,匹配项将以数组的形式返回:一个用于完整的键-值对,一个用于键,一个用于值。

        2
  •  2
  •   ghostdog74    16 年前

    regex是一个强大的工具,但有时它不是最好的方法。

    $string = "key-value;key1-value";
    $s = explode(";",$string);
    foreach($s as $k){
        $e = explode("-",$k);
        $array[$e[0]]=$e[1];
    }
    print_r($array);
    
        3
  •  2
  •   Lukman    16 年前

    preg_match_all() 相反可能是这样的:

    $matches = $parameters = array();
    $input = 'key-value;key1-value1;key2-value2;key123-value123;';
    
    preg_match_all("/(\w+)-([^-;]+)/", $input, $matches, PREG_SET_ORDER);
    
    foreach ($matches as $match) {
       $parameters[$match[1]] = $match[2];
    }
    
    print_r($parameters);
    

    编辑:

    要首先验证输入字符串是否符合模式,只需使用:

    if (preg_match("/^((\w+)-([^-;]+);)+$/", $input) > 0) {
        /* do the preg_match_all stuff */
    }       
    

    EDIT2:最后的分号是可选的

    if (preg_match("/^(\w+-[^-;]+;)*\w+-[^-;]+$/", $input) > 0) {
        /* do the preg_match_all stuff */
    }       
    
        4
  •  0
  •   Ignacio Vazquez-Abrams    16 年前

    否。较新的匹配将覆盖较旧的匹配。也许是 limit explode()

        5
  •  0
  •   KARASZI István    16 年前

    这个解决方案怎么样:

    $samples = array(
        "good" => "key-value;key1-value;key2-value;key5-value;key-value;",
        "bad1" => "key-value-value;key1-value;key2-value;key5-value;key-value;",
        "bad2" => "key;key1-value;key2-value;key5-value;key-value;",
        "bad3" => "k%ey;key1-value;key2-value;key5-value;key-value;"
    );
    
    foreach($samples as $name => $value) {
        if (preg_match("/^(\w+-\w+;)+$/", $value)) {
            printf("'%s' matches\n", $name);
        } else {
            printf("'%s' not matches\n", $name);
        }
    }
    
        6
  •  0
  •   Matteo Riva    16 年前

    我不认为您可以用一个regexp同时进行数据验证和提取,因为您需要锚( ^ $ )用于验证和 preg_match_all() 对于数据,但如果将锚点与 它将只返回最后一个匹配的集。