我试图使用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}
,但我不知道如何找到第二个模板的所有出现,以便我以后可以使用它们on以及如何停止搜索是否有</table>
表结束标记。所以请帮忙
问题已得到解答,因此要在原始表格标记<thead><tbody><tfoot>
中添加下一级别的问题。在输出表中,应该重建原始表的结构,所以我的意思是如果原始表的第一行是<thead>
标记的一部分,它应该在<thead>
中是所有输出表。
答案 0 :(得分:0)
您可以通过执行循环来实现此目的,其中每次迭代将添加下一个&#34;表格中断&#34;与preg_replace
(但最后见免责声明)。建议的正则表达式将找到以下组:
<table>
标记的最后一次出现以及其后的第一行,或者,如果有thead
和/或tbody
标记,则直至结束{{ 1}}标记,包括开头</thead>
标记(如果有)。然后展望未来,确保至少还有一行。
通过该信息,单个&#34;表格中断&#34;可以注入HTML字符串。
如果表有一个<tbody>
部分(然后也应该在表的每个分区中重复),我们将不会有这些信息,因为它发生在输入的最后。因此,在循环开始之前,需要单独解析以提取页脚。
这是假设输入在变量tfooter
中的代码:
$html
在eval.in上看到它。
以下是主要正则表达式中的一些要点:
// 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;
:我使用此作为正则表达式分隔符而不是#
,以避免在正则表达式本身内转义/
。如果你需要使用/
作为分隔符,那么将每个/
转义为/
:一个反斜杠用于正则表达式,另一个用于在字符串文字的上下文中转义反斜杠。
\\/
:确保我们即将匹配的标签之后没有其他(?!.*<table)
标记。这是一个消极的展望。
<table>
:抓取4行,并且正面向前看(((?:.*?/tr>(?=\s*<tr)){4})
)要求每行紧跟另一行。 (?= )
模式不会创建捕获组,但外部括号会创建一个。
如果替换只会再次注入2个捕获的组(即(?: )
),那么什么都不会改变。附加$1$2
将关闭表(使用页脚)并通过重用第一个捕获组来启动下一个。这将包含包含第一行和/或表头的开始$tableEnd\n$1
标记。
虽然上述内容在很多情况下都可以使用,但很有可能打破它,因为正则表达式不是解析/解释HTML的理想方法。你应该真的使用DOM api,PHP有一个:<table>
。