【问题标题】:PHP regex to match key value pairs from a given stringPHP正则表达式匹配给定字符串中的键值对
【发布时间】:2016-10-20 16:53:56
【问题描述】:

希望有人能帮忙。

我有一个字符串如下

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

现在我正在尝试从每个键、值对创建一个数组,但是对于 preg_match_all() 的正则表达式严重失败

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

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
    )
)

如果我能从给定的字符串中获得任何帮助或示例,我将不胜感激。

【问题讨论】:

  • 只是好奇,但您为什么要创建并尝试解析一种全新的序列化格式?为什么不直接使用 JSON 或已经拥有完整库的类似标准来解析和获取正确的值。使用正则表达式进行这项工作的唯一方法是使其成为可以匹配方括号的递归正则表达式,这并不容易。在遇到特殊字符(逗号、等号或方括号)并使用它之前,您几乎可以更好地遍历每个字符。

标签: php arrays regex


【解决方案1】:

正则表达式不是处理递归匹配的正确工具。您可以编写解析器而不是正则表达式(或使用 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 => hourly,minutely 而不是 exclude => array(hourly, minutely))。我认为这是您的格式不一致,我在编写解析器时考虑了“正确”版本。

【讨论】:

  • 谢谢,这给了我想要的输出,但可能你们俩都是对的,我应该尝试不同的方法,而不是把事情复杂化,我想我倾向于把事情复杂化。
  • 是的,您绝对应该选择另一种方法。保持简单是我们所有人的原则。
【解决方案2】:

如果你不想要解析器,你也可以试试这段代码。它将您的字符串转换为 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);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-05
    • 2013-12-25
    相关资源
    最近更新 更多