为什么这个正则表达式只匹配最后一次出现的模式
Why does this regex only mach the last occurence of the pattern
我正在尝试创建一个正则表达式,它将用标记代码创建 html。
尝试替换 [table] 标记的一部分时,它只会替换最后一次出现的标记。
我有以下正则表达式 (PHP):
/(\[table].*)\[\|](.*\[\/table])/s
替换模式:
</td><td>
以及以下测试字符串:
[table]<thead>
<th>head1</th><th>head2</th></thead>
[*]test1[|]test2
[*]test1[|]test2
[/table]
它应该产生以下内容:
[table]<thead>
<th>head1</th><th>head2</th></thead>
[*]test1</td><td>test2
[*]test1</td><td>test2
[/table]
但它实际上产生了这个:
[table]<thead>
<th>head1</th><th>head2</th></thead>
[*]test1[|]test2
[*]test1</td><td>test2
[/table]
问题在于,[|]
用于其他标记代码,但不应替换为 </td><td>
澄清一下:
我有一个 table "bb-code"
[table]
[**]header1[||]header2[||]header3[||]...[/**]
[*]child1.1[|]child1.2[|]child1.3[|]...
[*]child2.1[|]child2.2[|]child2.3[|]...
[*]child3.1[|]child3.2[|]child3.3[|]...
[*]...[|]...[|]...[|]...
[/table]
我希望这个变成这个:
<table class="ui compact stripet yellow table">
<thead>
<tr>
<th>header1</th>
<th>header2</th>
<th>header3</th>
<th>....</th>
</tr>
</thead>
<tbody>
<tr>
<td>child1.1</td>
<td>child1.2</td>
<td>child1.3</td>
<td>...</td>
</tr>
<tr>
<td>child2.1</td>
<td>child2.2</td>
<td>child2.3</td>
<td>...</td>
</tr>
<tr>
<td>child3.1</td>
<td>child3.2</td>
<td>child3.3</td>
<td>...</td>
</tr>
</tbody>
</table>
好吧,睡前我有几分钟的时间在我的手机上 phone,所以我 运行 听取了 Wiktor 的评论并搞了一系列 preg_
功能来尝试将您的 bbcode 转换为 html。我对 bbcode 没有任何经验,所以我纯粹是在处理您的示例输入,而不考虑边缘情况。我认为 php 某处有一个 bbcode 解析器库,但我不知道你的 bbcode 语法是否是标准的。
一些已实施的模式分解。
首先,隔离文档中每个完整的 [table]...[/table]
字符串。 (Regex101 Demo) ~\[table]\R*([^[]*(?:\[(?!/?table])[^[]*)*)\R*\[/table]~
将匹配字符串并将完全匹配作为 $m[0]
传递,将 table 标记之间的子字符串作为 $m[1]
传递给 BBTableToHTML()
。
接下来,BBTableToHTML()
将对 $m[1]
字符串进行 3 次单独传递。这些模式中的每一个都会将它们各自匹配的字符串发送到关联的自定义函数和 return 修改后的字符串。
在将更新的 $m[1]
从 BBTableToHTML()
发送回 echo
之前,您想要的 <table...>
和 </table>
标签将在书挡 $m[1]
.
preg_replace_callback_array()
模式的演示:
~\[\*\*]([^[]*(?:\[(?!/?\*\*])[^[]*)*)\[/\*\*]~
https://regex101.com/r/thINHQ/2
~(?:\[\*].*\R*)+~
https://regex101.com/r/thINHQ/3
~\[\*](.*)~
https://regex101.com/r/thINHQ/4
代码:(Demo)
$bbcode = <<<BBCODE
[b]Check out this demo[/b]
¯\_(ツ)_/¯
[table]
[**]header1[||]header2[||]header3[||]...[/**]
[*]child1.1[|]child1.2[|]child1.3[|]...
[*]child2.1[|]child2.2[|]child2.3[|]...
[*]child3.1[|]child3.2[|]child3.3[|]...
[*]...[|]...[|]...[|]...
[/table]
simple text
[table]
[**]a 1[||]and a 2[/**]
[*]A[|]B
[*]C[|]D
[/table]
[s]3, you're out[/s]
blah
BBCODE;
function BBTableToHTML($m) {
return "<table class=\"ui compact stripet yellow table\">\n" .
preg_replace_callback_array(
[
'~\[\*\*]([^[]*(?:\[(?!/?\*\*])[^[]*)*)\[/\*\*]~' => 'BBTHeadToHTML',
'~(?:\[\*].*\R*)+~' => 'BBTBodyToHTML',
'~\[\*](.*)~' => 'BBTBodyRowToHTML'
],
$m[1]
) .
"</table>";
}
function BBTHeadToHTML($m) {
return "\t<thead>\n" .
"\t\t<tr>\n\t\t\t<th>" . str_replace('[||]', "</th>\n\t\t\t<th>", $m[1]) . "</th>\n\t\t</tr>\n" .
"\t</thead>";
}
function BBTBodyToHTML($m) {
return "\t<tbody>\n{$m[0]}\t</tbody>\n";
}
function BBTBodyRowToHTML($m) {
return "\t\t<tr>\n\t\t\t<td>" . str_replace('[|]', "</td>\n\t\t\t<td>", $m[1]) . "</td>\n\t\t</tr>";
}
echo preg_replace_callback(
'~\[table]\R*([^[]*(?:\[(?!/?table])[^[]*)*)\R*\[/table]~',
'BBTableToHTML',
$bbcode
);
输出:
[b]Check out this demo[/b]
¯\_(ツ)_/¯
<table class="ui compact stripet yellow table">
<thead>
<tr>
<th>header1</th>
<th>header2</th>
<th>header3</th>
<th>...</th>
</tr>
</thead>
<tbody>
<tr>
<td>child1.1</td>
<td>child1.2</td>
<td>child1.3</td>
<td>...</td>
</tr>
<tr>
<td>child2.1</td>
<td>child2.2</td>
<td>child2.3</td>
<td>...</td>
</tr>
<tr>
<td>child3.1</td>
<td>child3.2</td>
<td>child3.3</td>
<td>...</td>
</tr>
<tr>
<td>...</td>
<td>...</td>
<td>...</td>
<td>...</td>
</tr>
</tbody>
</table>
simple text
<table class="ui compact stripet yellow table">
<thead>
<tr>
<th>a 1</th>
<th>and a 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>A</td>
<td>B</td>
</tr>
<tr>
<td>C</td>
<td>D</td>
</tr>
</tbody>
</table>
[s]3, you're out[/s]
blah
我正在尝试创建一个正则表达式,它将用标记代码创建 html。
尝试替换 [table] 标记的一部分时,它只会替换最后一次出现的标记。
我有以下正则表达式 (PHP):
/(\[table].*)\[\|](.*\[\/table])/s
替换模式:
</td><td>
以及以下测试字符串:
[table]<thead>
<th>head1</th><th>head2</th></thead>
[*]test1[|]test2
[*]test1[|]test2
[/table]
它应该产生以下内容:
[table]<thead>
<th>head1</th><th>head2</th></thead>
[*]test1</td><td>test2
[*]test1</td><td>test2
[/table]
但它实际上产生了这个:
[table]<thead>
<th>head1</th><th>head2</th></thead>
[*]test1[|]test2
[*]test1</td><td>test2
[/table]
问题在于,[|]
用于其他标记代码,但不应替换为 </td><td>
澄清一下: 我有一个 table "bb-code"
[table]
[**]header1[||]header2[||]header3[||]...[/**]
[*]child1.1[|]child1.2[|]child1.3[|]...
[*]child2.1[|]child2.2[|]child2.3[|]...
[*]child3.1[|]child3.2[|]child3.3[|]...
[*]...[|]...[|]...[|]...
[/table]
我希望这个变成这个:
<table class="ui compact stripet yellow table">
<thead>
<tr>
<th>header1</th>
<th>header2</th>
<th>header3</th>
<th>....</th>
</tr>
</thead>
<tbody>
<tr>
<td>child1.1</td>
<td>child1.2</td>
<td>child1.3</td>
<td>...</td>
</tr>
<tr>
<td>child2.1</td>
<td>child2.2</td>
<td>child2.3</td>
<td>...</td>
</tr>
<tr>
<td>child3.1</td>
<td>child3.2</td>
<td>child3.3</td>
<td>...</td>
</tr>
</tbody>
</table>
好吧,睡前我有几分钟的时间在我的手机上 phone,所以我 运行 听取了 Wiktor 的评论并搞了一系列 preg_
功能来尝试将您的 bbcode 转换为 html。我对 bbcode 没有任何经验,所以我纯粹是在处理您的示例输入,而不考虑边缘情况。我认为 php 某处有一个 bbcode 解析器库,但我不知道你的 bbcode 语法是否是标准的。
一些已实施的模式分解。
首先,隔离文档中每个完整的 [table]...[/table]
字符串。 (Regex101 Demo) ~\[table]\R*([^[]*(?:\[(?!/?table])[^[]*)*)\R*\[/table]~
将匹配字符串并将完全匹配作为 $m[0]
传递,将 table 标记之间的子字符串作为 $m[1]
传递给 BBTableToHTML()
。
接下来,BBTableToHTML()
将对 $m[1]
字符串进行 3 次单独传递。这些模式中的每一个都会将它们各自匹配的字符串发送到关联的自定义函数和 return 修改后的字符串。
在将更新的 $m[1]
从 BBTableToHTML()
发送回 echo
之前,您想要的 <table...>
和 </table>
标签将在书挡 $m[1]
.
preg_replace_callback_array()
模式的演示:
~\[\*\*]([^[]*(?:\[(?!/?\*\*])[^[]*)*)\[/\*\*]~
https://regex101.com/r/thINHQ/2~(?:\[\*].*\R*)+~
https://regex101.com/r/thINHQ/3~\[\*](.*)~
https://regex101.com/r/thINHQ/4
代码:(Demo)
$bbcode = <<<BBCODE
[b]Check out this demo[/b]
¯\_(ツ)_/¯
[table]
[**]header1[||]header2[||]header3[||]...[/**]
[*]child1.1[|]child1.2[|]child1.3[|]...
[*]child2.1[|]child2.2[|]child2.3[|]...
[*]child3.1[|]child3.2[|]child3.3[|]...
[*]...[|]...[|]...[|]...
[/table]
simple text
[table]
[**]a 1[||]and a 2[/**]
[*]A[|]B
[*]C[|]D
[/table]
[s]3, you're out[/s]
blah
BBCODE;
function BBTableToHTML($m) {
return "<table class=\"ui compact stripet yellow table\">\n" .
preg_replace_callback_array(
[
'~\[\*\*]([^[]*(?:\[(?!/?\*\*])[^[]*)*)\[/\*\*]~' => 'BBTHeadToHTML',
'~(?:\[\*].*\R*)+~' => 'BBTBodyToHTML',
'~\[\*](.*)~' => 'BBTBodyRowToHTML'
],
$m[1]
) .
"</table>";
}
function BBTHeadToHTML($m) {
return "\t<thead>\n" .
"\t\t<tr>\n\t\t\t<th>" . str_replace('[||]', "</th>\n\t\t\t<th>", $m[1]) . "</th>\n\t\t</tr>\n" .
"\t</thead>";
}
function BBTBodyToHTML($m) {
return "\t<tbody>\n{$m[0]}\t</tbody>\n";
}
function BBTBodyRowToHTML($m) {
return "\t\t<tr>\n\t\t\t<td>" . str_replace('[|]', "</td>\n\t\t\t<td>", $m[1]) . "</td>\n\t\t</tr>";
}
echo preg_replace_callback(
'~\[table]\R*([^[]*(?:\[(?!/?table])[^[]*)*)\R*\[/table]~',
'BBTableToHTML',
$bbcode
);
输出:
[b]Check out this demo[/b]
¯\_(ツ)_/¯
<table class="ui compact stripet yellow table">
<thead>
<tr>
<th>header1</th>
<th>header2</th>
<th>header3</th>
<th>...</th>
</tr>
</thead>
<tbody>
<tr>
<td>child1.1</td>
<td>child1.2</td>
<td>child1.3</td>
<td>...</td>
</tr>
<tr>
<td>child2.1</td>
<td>child2.2</td>
<td>child2.3</td>
<td>...</td>
</tr>
<tr>
<td>child3.1</td>
<td>child3.2</td>
<td>child3.3</td>
<td>...</td>
</tr>
<tr>
<td>...</td>
<td>...</td>
<td>...</td>
<td>...</td>
</tr>
</tbody>
</table>
simple text
<table class="ui compact stripet yellow table">
<thead>
<tr>
<th>a 1</th>
<th>and a 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>A</td>
<td>B</td>
</tr>
<tr>
<td>C</td>
<td>D</td>
</tr>
</tbody>
</table>
[s]3, you're out[/s]
blah