PHP正则表达式匹配给定字符串

时间:2016-10-20 16:53:56

标签: php arrays regex

我希望有人可以提供帮助。

我有一个字符串如下

$string = 'latitude=46.6781471,longitude=13.9709534,options=[units=auto,lang=de,exclude=[hourly,minutely]]';

现在我正在尝试的是从每个键值对中创建一个数组但是使用regex为preg_match_all()严重失败

目前我的尝试没有给出所需的结果,创建了key =>只要没有括号,值对就可以工作,但是如果键包含示例中括号内的键/值对,我完全不知道如何实现多维数组。

Array (
[0] => Array
    (
        [0] => latitude=46.6781471,
        [1] => longitude=13.9709534,
        [2] => options=[units=si,
        [3] => lang=de,
    )

[1] => Array
    (
        [0] => latitude
        [1] => longitude
        [2] => options=[units
        [3] => lang
    )

.. and so on

最终我希望得到如下结果。

Array (
[latitude] => 46.6781471
[longitude] => 13.9709534
[options] => Array
    (
        [units] => auto
        [exclude] => hourly,minutely
    )
)

如果我能从给定的字符串中实现这一点,我将不胜感激。

2 个答案:

答案 0 :(得分:2)

正则表达式不是处理递归匹配的正确工具。您可以编写解析器而不是正则表达式(或使用JSON,查询字符串,XML或任何其他常用格式):

function parseOptionsString($string) {

    $length        = strlen($string);
    $key           = null;
    $contextStack  = array();
    $options       = array();

    $specialTokens = array('[', ']', '=', ',');
    $buffer     = '';

    $currentOptions = $options;

    for ($i = 0; $i < $length; $i++) {
        $currentChar = $string[$i];

        if (!in_array($currentChar, $specialTokens)) {
            $buffer .= $currentChar;
            continue;
        }

        if ($currentChar == '[') {
            array_push($contextStack, [$key, $currentOptions]);
            $currentOptions[$key] = array();
            $currentOptions       = $currentOptions[$key];
            $key                  = '';
            $buffer               = '';
            continue;
        }

        if ($currentChar == ']') {
            if (!empty($buffer)) {
                if (!empty($key)) {
                    $currentOptions[$key] = $buffer;    
                } else {
                    $currentOptions[] = $buffer;
                }
            }


            $contextInfo     = array_pop($contextStack);
            $previousContext = $contextInfo[1];
            $thisKey         = $contextInfo[0];

            $previousContext[$thisKey] = $currentOptions;

            $currentOptions        = $previousContext;
            $buffer                = '';
            $key                   = '';
            continue;
        }

        if ($currentChar == '=') {
            $key    = $buffer;
            $buffer = '';
            continue;
        }

        if ($currentChar == ',') {

            if (!empty($key)) {
                $currentOptions[$key] = $buffer; 
            } else if (!empty($buffer)) {
                $currentOptions[] = $buffer;
            }
            $buffer        = '';
            $key           = '';
            continue;
        }

    }

    if (!empty($key)) {
        $currentOptions[$key] = $buffer;
    }

    return $currentOptions;
} 

这给出了以下输出:

print_r(parseOptionsString($string));

Array
(
    [latitude] => 46.6781471
    [longitude] => 13.9709534
    [options] => Array
        (
            [units] => auto
            [lang] => de
            [exclude] => Array
                (
                    [0] => hourly
                    [1] => minutely
                )

        )

)

另请注意,对于仅包含逗号分隔值的数组,您需要特殊语法(exclude = [hourly,minutely]变为exclude =&gt; hourly,minutely和not exclude =&gt; array(每小时,每分钟))。我认为这与您的格式不一致,我在编写解析器时考虑到了“正确”的版本。

答案 1 :(得分:0)

如果您不想要解析器,您也可以尝试使用此代码。它将您的字符串转换为JSON并解码为数组。但正如其他人所说,我认为你应该尝试使用JSON的方法。如果您在JavaScript中通过XmlHttpRequest发送此字符串,则创建正确的JSON代码并不难发送。

$string = 'latitude=46.6781471,longitude=13.9709534,options=[units=auto,lang=de,exclude=[hourly,minutely]]';

$string = preg_replace('/([^=,\[\]\s]+)/', '"$1"', $string);

$string = '{' . $string . '}';
$string = str_replace('=', ':', $string);
$string = str_replace('[', '{', $string);
$string = str_replace(']', '}', $string);

$string = preg_replace('/({[^:}]*})/', '|$1|', $string);
$string = str_replace('|{', '[', $string);
$string = str_replace('}|', ']', $string);

$result = json_decode($string, true);

print_r($result);