我正在开发一个新的Symfony 2项目,该项目将成为Docker容器的面板管理。
在这个项目中,我正在使用exec()
PHP函数执行一些命令。
我正在尝试解析以下命令的输出:
docker create tutum/lamp:latest --name test 2>&1
当命令成功时,我将容器ID放在一个好的,易于使用的字符串中,但是当出现问题时,它不一样。结果是一个带有var =“data”语法的字符串,我想解析它以获得一个数组。
命令输出:
time="2015-06-21T11:33:26+02:00" level="fatal" msg="Error response from daemon: Conflict. The name \"test\" is already in use by container XXXXXXXX. You have to delete (or rename) that container to be able to reuse that name."
我希望有类似的东西:
Array( time => "2015-06-21T11:33:26+02:00", level => "fatal" ...);
我知道我必须进行正则表达式解析。过了一会儿(正则表达式和我不是最好的朋友)我得到这个正则表达式(在https://regex101.com/上测试):
/([a-zA-Z]+)="((.*)*)"/
我使用preg_split函数我不确定它是好的。
preg_split('/([a-zA-Z]+)="((.*)*)"/', $output)
结果是:
array(2) { [0]=> string(0) "" [1]=> string(0) "" }
你有什么建议可以帮助我吗? 非常感谢你的帮助。
答案 0 :(得分:1)
TL; DR:这应该有效:
preg_match_all(',([a-z]+)="((?:[^"]|\\\\")*[^\\\\])",', $a, $matches, PREG_SET_ORDER);
var_dump($matches);
最后var_dump
打印以下数据结构,应该易于处理:
array(3) {
[0] => array(3) {
[0] => string(32) "time="2015-06-21T11:33:26+02:00""
[1] => string(4) "time"
[2] => string(25) "2015-06-21T11:33:26+02:00"
}
[1] => array(3) {
[0] => string(13) "level="fatal""
[1] => string(5) "level"
[2] => string(5) "fatal"
}
[2] => array(3) {
[0] => string(179) "msg="Error response from daemon: Conflict. The name \\"test\\" is already in use by container XXXXXXXX. You have to delete (or rename) that container to be able to reuse that name.""
[1] => string(3) "msg"
[2] => string(173) "Error response from daemon: Conflict. The name \\"test\\" is already in use by container XXXXXXXX. You have to delete (or rename) that container to be able to reuse that name."
}
}
正则表达式解释说:
([a-z]+) # Match the label ("time", "level" or "msg")
= # Self-explanatory
"((?:[^"]|\\\\")*[^\\\\])" # This is the tricky part:
# Match the quoted string; this is a sequence
# of (a) non-quote characters ([^"]) or
# (b) escaped quote characters (\\\\").
其他一些说明:
preg_split
使用正则表达式来匹配应该拆分字符串的标记。在这种情况下,这不是你想要的;您希望通过正则表达式返回匹配的字符串部分。为此,您应该使用preg_match
(或者,如果您希望模式多次匹配),preg_match_all
。PREG_SET_ORDER
的{{1}}标记。此标志使preg_match_all
结果从输出消息中为每个标签包含一行,这使得数据结构易于处理。试着看看如果你把它拿出来会发生什么。答案 1 :(得分:1)
这是因为greedy dot会将你的字符串吃掉到最后"
。让它变得懒惰,会这样做:
if(preg_match_all('/(\w+)="(.*?)(?<!\\\)"/s', $str, $out))
print_r(array_combine($out[1], $out[2]));
\w
是[a-zA-Z0-9_]
的{{3}}。使用后备(?<!\\\)
来逃脱报价(short)。
使用s
标志使点匹配换行符。 see regex101,输出到:
阵 ( [时间] =&gt; 2015-06-21T11:33:26 + 02:00 [level] =&gt;致命 [msg] =&gt;来自守护程序的错误响应:冲突。名称\&#34; test \&#34;已被容器XXXXXXXX使用。您必须删除(或重命名)该容器才能重用该名称。 )