将 mikrotik 脚本拆分为 key/value php 数组
Splitting mikrotik script into an key/value php array
比方说,我在 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,匹配除 "
以外的任何字符或空白字符
)
关闭分支重置组
例如
$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',
)
比方说,我在 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,匹配除"
以外的任何字符或空白字符
)
关闭分支重置组
例如
$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',
)