如何在preg_match_all的正则表达式中更正子模式的结果?

时间:2016-05-14 17:02:42

标签: php regex preg-match-all

我有这段代码:

$query = 'CREATE table "msg" ( "myid" INT(10) UNSIGNED , "user" INT(10) UNSIGNED , "new_mes" SMALLINT(5) UNSIGNED , "total_mes" MEDIUMINT(8) UNSIGNED , "lastdate" DATETIME , PRIMARY KEY ("ids"), KEY ("lastdate") )'; 

我正在尝试使用此子配件获取主键和密钥:

preg_match_all('/(?:\WPRIMARY\W*KEY\W?\()(?P<PRIMARY_KEY>[^)]+)|'.
        '(?:\W*KEY\W?\()(?P<KEY>[^)]+)/i',$query,$results);
        $primary_key = isset($results['PRIMARY_KEY'][0]) ? $results['PRIMARY_KEY'][0] : '';
        $key = isset($results['KEY'][0]) ? $results['KEY'][0] : '';
    print_r($results);

我得到了这个输出:

Array
(
    [0] => Array
        (
            [0] =>  PRIMARY KEY ("ids"
            [1] => ),KEY ("lastdate"
        )

    [PRIMARY_KEY] => Array
        (
            [0] => "ids"
            [1] => 
        )

    [1] => Array
        (
            [0] => "ids"
            [1] => 
        )

    [KEY] => Array
        (
            [0] => 
            [1] => "lastdate"
        )

    [2] => Array
        (
            [0] => 
            [1] => "lastdate"
        )
)

我查找用双引号括起来的单词。结果几乎找不到但我更愿意得到两个词&#34; ids&#34; &#34; lastdate&#34;在第一个索引[0]。你能解释为什么第一个单词放在第一个索引中,而第二个单词放在第二个索引中吗?为什么第二个和第一个索引上都有空字符串。

有没有办法如何在索引0上获得两个单词?只是为了简化代码。

1 个答案:

答案 0 :(得分:2)

您可以在右上角的栏中查看正则表达式如何与Regex101一起使用。

另一种完成工作的方式(see online demo):

<?php
// I added a primary key `myid` to demonstrate a capture with several keywords
$query = 'CREATE table "msg" ( "myid" INT(10) UNSIGNED , "user" INT(10) UNSIGNED , "new_mes" SMALLINT(5) UNSIGNED , "total_mes" MEDIUMINT(8) UNSIGNED , "lastdate" DATETIME , PRIMARY KEY ("ids", "myid"), KEY ("lastdate") )'; 

// 1. Note the \b anchor to ensure that the capture begins at the start of a word
// 2. PREG_SET_ORDER to keep structure simplier
preg_match_all('#\b((?:PRIMARY\s*?)?KEY) \(([^\)]*)\)#i', $query, $results, PREG_SET_ORDER);

$primary_keys = [];
$keys = [];

foreach ($results as $result) {
    $values = explode(',', $result[2]); // get separate words
    array_walk($values, function (&$v) { $v = trim($v, ' "'); }); // remove quotes and spaces
    if (0 === stripos($result[1], 'PRIMARY')) {
        $primary_keys = array_merge($primary_keys, $values);
    }
    else {
        $keys = array_merge($keys, $values);
    }
}

echo "Found primary keys:\n";
print_r($primary_keys);
echo "Found keys:\n";
print_r($keys);

echo "\n\$results:\n";
print_r($results);

<强>结果:

Found primary keys:
Array
(
    [0] => ids
    [1] => myid
)
Found keys:
Array
(
    [0] => lastdate
)

$results:
Array
(
    [0] => Array
        (
            [0] => PRIMARY KEY ("ids", "myid")
            [1] => PRIMARY KEY
            [2] => "ids", "myid"
        )

    [1] => Array
        (
            [0] => KEY ("lastdate")
            [1] => KEY
            [2] => "lastdate"
        )

)

您可以在Regex101上看到,this new version效率更高the old one,步数为377步,捕捉结果为904步。