我正在尝试使用 regExps 进行排序,所以我在途中遇到了一个问题:问题是我有一些带有纯文本的随机 HTML 文件,并且只有一个表格。文本可以在表格前后,表格不包括<thead><tbody><tfoot> rowspan
等等。因此,我需要将此表拆分为多个表,每个表 5 行,最后一个表不超过 5 行,并在每个表中重复原始表的第一个字符串。例如:
<table>
<tr>
<td>A</td><td>B</td>
</tr>
<tr>
<td>A1</td><td>B1</td>
</tr>
<tr>
<td>C</td><td>D</td>
</tr>
<tr>
<td>E</td><td>F</td>
</tr>
<tr>
<td>E1</td><td>F1</td>
</tr>
<tr>
<td>E2</td><td>F2</td>
</tr>
<tr>
<td>E3</td><td>F3</td>
</tr>
<tr>
<td>E4</td><td>F4</td>
</tr>
</table>
应该变成:
<table>
<tr>
<td>A</td><td>B</td><--!!!(not needed to be in code)-->
</tr>
<tr>
<td>A1</td><td>B1</td>
</tr>
<tr>
<td>C</td><td>D</td>
</tr>
<tr>
<td>E</td><td>F</td>
</tr>
<tr>
<td>E1</td><td>F1</td>
</tr>
</table>
<table>
<tr>
<td>A</td><td>B</td><--!!!(not needed to be in code)-->
</tr>
<tr>
<td>E2</td><td>F2</td>
</tr>
<tr>
<td>E3</td><td>F3</td>
</tr>
<tr>
<td>E4</td><td>F4</td>
</tr>
</table>
这些东西我需要在 PHP 中使用 PCRE 来完成,包括大量的模板和更改。所以我在实现上有问题。现在我可以找到像这样的第一行<table>\s*?(<tr>(?:\s|.)*?<\/tr>)
和 4 行,(<tr>(?:\s|.)*?<\/tr>\s*){1,4}
但我不知道如何找到第二个模板的所有出现,以便稍后使用它们以及如何停止搜索是否有</table>
表格结束标记。所以请帮忙
问题已得到解答,所以下一级添加原始表格标签<thead><tbody><tfoot>
。在输出表中,应该重建原始表的结构,所以我的意思是如果原始表的第一行是<thead>
标签的一部分,它应该在<thead>
所有输出表中。
您可以通过执行一个循环来实现这一点,其中每次迭代都会添加下一个“表格中断” preg_replace
(但请参阅最后的免责声明)。建议的正则表达式将找到以下组:
<table>
标签的最后一次出现以及它后面的第一行,或者,如果有thead
和/或tbody
标签,直到结束</thead>
标签,<tbody>
如果有开始标签,则包括开始标签。然后它还会向前看以确保至少还有一行。
有了这些信息,就可以将单个“表格中断”注入到 HTML 字符串中。
如果表有一个tfooter
部分(它也应该在表的每个分区中重复),我们还没有那个信息,因为它出现在输入的最后。因此,在循环开始之前,需要进行单独的解析以提取页脚。
这是假设输入在变量中的代码$html
:
// Extract the footer part (if there is one) and closing table tag
preg_match("#(\s*(</tbody|<tfooter).*?)?</table>#s", $html, $tableEnd);
$tableEnd = $tableEnd[0];
// Add a table break in each iteration as long as the last partition has more than 4 rows:
while (true) {
$res = preg_replace("#(<table(?!.*<table).*?/tr>(?:.*?/thead>)?(?:.*?<tbody>)?)((?:.*?/tr>(?=\s*<tr)){4})#s",
"$1$2$tableEnd\n$1", $html);
if (strlen($res) === strlen($html)) break;
$html = $res;
}
echo $res;
看看它在eval.in 上运行。
以下是主要正则表达式中的一些亮点:
#
:我使用它作为正则表达式分隔符,而不是/
为了避免需要/
在正则表达式内部转义。如果您需要/
用作分隔符,则将每个转义/
为\\/
:一个反斜杠用于正则表达式,另一个用于在字符串文字的上下文中转义该反斜杠。
(?!.*<table)
: 确保<table>
在我们即将匹配的标签之后没有其他标签。这是一个消极的展望。
((?:.*?/tr>(?=\s*<tr)){4})
: 抓取 4 行,并积极向前看 ( (?= )
) 要求每行紧跟另一行。该(?: )
模式不会创建捕获组,但外括号确实创建了一个捕获组。
如果替换只是再次注入 2 个捕获的组(即$1$2
),那么什么都不会改变。附加$tableEnd\n$1
将关闭表格(带有页脚)并通过重用第一个捕获组开始下一个。这将<table>
包含包含第一行和/或表标题的开始标记。
尽管上述方法在许多情况下可能有效,但很可能会破坏它,因为正则表达式不是解析/解释 HTML 的理想方式。您真的应该为此使用 DOM api,而 PHP 有一个:DOMDocument
.
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句