将mikrotik脚本拆分为键/值php数组

问题描述

比方说,我在mikrotik路由器中有以下脚本,我想提取一个包含键和值的数组,如果还有另一个包含 = 字符的值,该怎么做

add name=100YER on-login=":do {:put \"a\";} on-error={};" rate-limit=256k/512k

结果应如下所示:

$result=array ('name'=>'100YER',on-login=>':do {:put \"a\";} on-error={};','rate-limit'=>'256k/512k');

我使用此正则表达式将其除以 = ,但问题出在登录值上。

if (preg_match_all('/[^=]+/i',$response,$MATCHES) ){
        //
}

解决方法

您可以将2个捕获组与分支重置组一起使用:

(\w+(?:-\w+)*)=(?|"((?:[^"]+|(?<=\\)")++)"|([^"\s]+))

说明

  • (捕获第1组
    • \w+(?:-\w+)*匹配1个以上字符的字符,然后可选地跟一个-和1个以上字符的字符
  • )关闭第1组
  • =字面上匹配
  • (?|分支重置组
    • "(匹配"并开始第2组
      • (?:[^"]+|(?<=\\)")++匹配除"\"之外的所有字符
    • )"关闭第2组并匹配"
    • |
    • ([^"\s]+)捕获第3组,匹配"或空白char
    • 以外的任何字符
  • )关闭分支重置组

Regex demo | Php demo

例如

$re = '/(\w+(?:-\w+)*)=(?|"((?:[^"]+|(?<=\\\\)")++)"|([^"\s]+))/';
$str = 'add name=100YER on-login=":do {:put \\"a\\";} on-error={};" rate-limit=256k/512k';

preg_match_all($re,$str,$matches);
$result = array_combine($matches[1],$matches[2]);
print_r($result);

输出

Array
(
    [name] => 100YER
    [on-login] => :do {:put \"a\";} on-error={};
    [rate-limit] => 256k/512k
)
,

要改善@Thefourthbird的模式,请使用PHP: Regex to ignore escaped quotes within quotes中“最佳”技术的智慧。这样不仅可以提高步数的图形效率,还可以更准确地区分字面使用的反斜杠和转义的反斜杠。

否则,我完全同意分支重置最适合将目标子字符串保留在preg_match_all()输出数组的一致列中。

代码:(Demo

$string = <<<MIKROTIK
add name=100YER on-login=":do {:put \"a\";} on-error={};" rate-limit=256k/512k
MIKROTIK;

var_export(
    preg_match_all(
        '~(\w+(?:-\w+)*)=(?|"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|([^" ]+))~',$string,$out
    )
    ? array_combine($out[1],$out[2])
    : []
);

输出:

array (
  'name' => '100YER','on-login' => ':do {:put \\"a\\";} on-error={};','rate-limit' => '256k/512k',)