我有一个文件的结构是一个大型多维结构,类似于json,但距离不够近,无法使用json库。
数据看起来像这样:
alpha {
beta {
charlie;
}
delta;
}
echo;
foxtrot {
golf;
hotel;
}
我试图构建的regex(对于preg_match_all)应该与每个顶级父级匹配(由{}个大括号分隔),这样我就可以在匹配中递归,构建一个表示数据的多维php数组。
我尝试的第一个正则表达式是/(?<='{).*(?='})/s
,它贪婪地匹配大括号内的内容,但这并不完全正确,因为当顶级中有多个同级时,匹配太贪婪了。以下示例:
使用正则表达式/(?<='{).*(?='})/s
匹配如下:
匹配1:
beta {
charlie;
}
delta;
}
echo;
foxtrot {
golf;
hotel;
相反,结果应该是:匹配1:
beta {
charlie;
}
delta;
匹配2:
golf;
hotel;
那么regex向导,我这里缺少什么功能,或者我需要用php来解决这个问题?任何提示都非常欢迎:)
不能用正则表达式1执行此操作。
或者,如果要将深块与浅块匹配,可以使用'{[^'{'}]*?'}
和preg_replace_callback()
来存储值,并返回null
将其从字符串中擦除。回调将需要相应地嵌套值。
$heirarchalStorage = ...;
do {
$string = 'preg_replace_callback('#'{[^'{'}]*?'}#', function($block)
use(&$heirarchalStorage) {
// do your magic with $heirarchalStorage
// in here
return null;
}, $string);
} while (!empty($string));
不完整,未经测试,无保修
这种方法要求字符串也被封装在{}
中,否则最终的匹配不会发生,您将永远循环。
这是一项糟糕的大量(效率低下)工作,而这些工作可以通过众所周知的交换/存储格式(如JSON)轻松解决。
1我本来打算放"你可以,但是…",但我只想再说一次,"你不能"2
2不要
当然可以用正则表达式实现这一点。
preg_match_all(
'/([^'s]+)'s*{((?:[^{}]*|(?R))*)}/',
$yourStuff,
$matches,
PREG_SET_ORDER
);
这给了我以下匹配:
[1]=>
string(5) "alpha"
[2]=>
string(46) "
beta {
charlie;
}
delta;
"
和
[1]=>
string(7) "foxtrot"
[2]=>
string(22) "
golf;
hotel;
"
把它分解一下。
([^'s]+) # non-whitespace (block name)
's* # whitespace (between name and block)
{ # literal brace
( # begin capture
(?: # don't create another capture set
[^{}]* # everything not a brace
|(?R) # OR recurse
)* # none or more times
) # end capture
} # literal brace
仅供参考,这适用于n-deep级别的支架。
我认为您可能会通过匹配[a-zA-Z0-9][:blank]+{
和}
来使用preg_split
。您将能够通过遍历结果来构造您的数组。使用一个递归函数,当您匹配一个开始标记时,该函数会更深入,而在一个结束标记时,它会更上层。
否则,最干净的解决方案将是实现一个ANTLR语法!