当引号中嵌入其他括号时提取括号中的字符串
Extract string in brackets when there are other brackets embedded in quotes
我想从字符串中提取括号中的部分:
[list items='["one","two"]' ok="no" b="c"]
我正在使用以下 preg_match
调用:
preg_match('~\[([a-zA-Z0-9_]+)[ ]+([a-zA-Z0-9]+=[^\[]+)\]~s', $string,$match)
但是我对引号内出现的括号有疑问。
我有两个文件
theme.html
[list items=""one","[x]tw"'o"" ok="no" b="c""/]
@book
[button text="t'"extB1" name="ok"'" /]
Asdfz " s wr aw3r '
[button text="t"'extB2" name="no"'" /]
file.php
$string=file_get_contents('theme.html');
for (;;) {
if (!preg_match('~\[([a-zA-Z0-9_]+)[ ]+([a-zA-Z0-9]+=[^\[]+)\]~s', $string,$match)) {
exit;
}
$string=str_replace($match[0], '', $string);
echo "<pre><br>";
print_r($match);
echo "<br></pre>";
}
这是输出:
<pre><br>Array
(
[0] = [button text="textB1" name="ok"]
[1] = button
[2] = text="textB1" name="ok"
)
<br></pre>
<pre><br>Array
(
[0] = [button text="textB2" name="no"]
[1] = button
[2] = text="textB2" name="no"
)
<br></pre>
如您所见,输出不包括
[list items='["one","two"]' ok="no" b="c"]
我知道问题是由嵌入的方括号引起的,但我不知道如何更正代码以忽略它们。
您可以使用您的 preg_match
调用的这种变体:
if (!preg_match('~\[(\w+)\s+(\w+=(?:\'[^\']*\'|[^\[])+?)\]~s', $string, $match))
使用 \'[^\']*\'
它会检测引号的存在,并会抓取所有字符直到下一个引号,而不会阻塞左括号。仅当无法匹配时,它才会用于您拥有的部分:[^\[])+
。我在其中添加了一个 ?
,使其成为非贪婪的,这确保它不会获取结束 ]
.
还要注意[a-zA-Z_]
可以简写成\w
,而[ ]
可以写成\s
,这样也可以让其他的white-space ,我认为没问题。
在 eval.in 上查看 运行。
备选方案:只匹配完整的行
如果引号可以出现在任何地方而不能保证右括号出现在引号内,那么上面的方法将不起作用。
相反,我们可以要求匹配必须跨越文本中的完整行:
if (!preg_match('~^\s*\[(\w+)\s+(\w+=.*?)\]\s*$~sm', $string, $match))
在 eval.in 上查看 运行。
我想从字符串中提取括号中的部分:
[list items='["one","two"]' ok="no" b="c"]
我正在使用以下 preg_match
调用:
preg_match('~\[([a-zA-Z0-9_]+)[ ]+([a-zA-Z0-9]+=[^\[]+)\]~s', $string,$match)
但是我对引号内出现的括号有疑问。
我有两个文件
theme.html
[list items=""one","[x]tw"'o"" ok="no" b="c""/]
@book
[button text="t'"extB1" name="ok"'" /]
Asdfz " s wr aw3r '
[button text="t"'extB2" name="no"'" /]
file.php
$string=file_get_contents('theme.html');
for (;;) {
if (!preg_match('~\[([a-zA-Z0-9_]+)[ ]+([a-zA-Z0-9]+=[^\[]+)\]~s', $string,$match)) {
exit;
}
$string=str_replace($match[0], '', $string);
echo "<pre><br>";
print_r($match);
echo "<br></pre>";
}
这是输出:
<pre><br>Array
(
[0] = [button text="textB1" name="ok"]
[1] = button
[2] = text="textB1" name="ok"
)
<br></pre>
<pre><br>Array
(
[0] = [button text="textB2" name="no"]
[1] = button
[2] = text="textB2" name="no"
)
<br></pre>
如您所见,输出不包括
[list items='["one","two"]' ok="no" b="c"]
我知道问题是由嵌入的方括号引起的,但我不知道如何更正代码以忽略它们。
您可以使用您的 preg_match
调用的这种变体:
if (!preg_match('~\[(\w+)\s+(\w+=(?:\'[^\']*\'|[^\[])+?)\]~s', $string, $match))
使用 \'[^\']*\'
它会检测引号的存在,并会抓取所有字符直到下一个引号,而不会阻塞左括号。仅当无法匹配时,它才会用于您拥有的部分:[^\[])+
。我在其中添加了一个 ?
,使其成为非贪婪的,这确保它不会获取结束 ]
.
还要注意[a-zA-Z_]
可以简写成\w
,而[ ]
可以写成\s
,这样也可以让其他的white-space ,我认为没问题。
在 eval.in 上查看 运行。
备选方案:只匹配完整的行
如果引号可以出现在任何地方而不能保证右括号出现在引号内,那么上面的方法将不起作用。
相反,我们可以要求匹配必须跨越文本中的完整行:
if (!preg_match('~^\s*\[(\w+)\s+(\w+=.*?)\]\s*$~sm', $string, $match))
在 eval.in 上查看 运行。