Preg_replace() 使用非捕获组添加到字符串
Preg_replace() to add to string using non-capturing group
我有一段 HTML 标记,我需要为其添加特定的 CSS 规则。 HTML 是这样的:
<tr>
<td style="color:#555555;padding-top: 3px;padding-bottom: 20px;">In order to stop receiving similar emails, simply remove the relevant <a href="https://domain.tld/dashboard/" target="_blank">saved search</a> from your account.</td>
</tr>
正如你所看到的td
已经包含了一个style
标签,所以我的想法是匹配它的最后一个;
并用;
替换它加上我需要添加的规则...
问题是,虽然我使用了适当的非捕获组,但我仍然不知道如何正确地做到这一点...请看一下这个实验:https://regex101.com/r/qlVq6A/1
(<td.*style=".*)(;)(".*>)(?:In order to stop receiving)
另一方面,当我为最后一部分分配一个捕获组时(那里的英文文本只是为了确定我对哪个 td
感兴趣)它工作正常,但我觉得这是一种间接的方式来完成这项工作......看看这个实验:https://regex101.com/r/qhVatN/1
(<td.*style=".*)(;)(".*>In order to stop receiving)
有人可以向我解释为什么第一条路线不起作用吗?基本上,为什么非捕获组仍然捕获其中的文本...
在你的第二个模式中,你使用了 3 个捕获组,你使用了你想要在替换中添加的样式,第 3 个组包含 In order to stop receiving
,它将在替换中使用第 3 个组后出现。
但是在你的第一个模式中,你使用了一个非捕获组 (?:
并且它将 匹配 但不是替换的一部分。
请注意,当使用像这样的非捕获组时,您完全可以省略它,因为像这样的分组本身没有例如量词或交替没有其他目的。
您可以为示例字符串使用模式,但这很容易出错,使用 DOM 解析器是更好的选择。
仅使用 2 个捕获组编写模式的方法:
(<td[^>]*\bstyle="[^"]*;)([^"]*">In order to stop receiving)
替换使用中:
font-size: 80%;
说明
(
捕获 组 1
<td[^>]*
匹配 <td
然后可选地重复除 >
之外的任何字符
\bstyle="[^"]*;
匹配 style="
然后可选地重复匹配除 "
之外的任何字符,然后匹配最后一个分号(注意它现在是第 1 组的一部分)
)
关闭组 1
(
捕获 第 2 组
[^"]*">In order to stop receiving
可选择重复匹配除 :
之外的任何字符,然后匹配 ">
后跟预期的文本
)
关闭组 2
看到一个regex demo。
另一种不使用捕获组编写模式的选项使用 \K
忘记到目前为止匹配的内容,并使用正向前瞻 (?=
断言右侧的预期文本:
<td[^>]*\bstyle="[^"]*;\K(?=[^"]*">In order to stop receiving)
再看一个regex demo。
我有一段 HTML 标记,我需要为其添加特定的 CSS 规则。 HTML 是这样的:
<tr>
<td style="color:#555555;padding-top: 3px;padding-bottom: 20px;">In order to stop receiving similar emails, simply remove the relevant <a href="https://domain.tld/dashboard/" target="_blank">saved search</a> from your account.</td>
</tr>
正如你所看到的td
已经包含了一个style
标签,所以我的想法是匹配它的最后一个;
并用;
替换它加上我需要添加的规则...
问题是,虽然我使用了适当的非捕获组,但我仍然不知道如何正确地做到这一点...请看一下这个实验:https://regex101.com/r/qlVq6A/1
(<td.*style=".*)(;)(".*>)(?:In order to stop receiving)
另一方面,当我为最后一部分分配一个捕获组时(那里的英文文本只是为了确定我对哪个 td
感兴趣)它工作正常,但我觉得这是一种间接的方式来完成这项工作......看看这个实验:https://regex101.com/r/qhVatN/1
(<td.*style=".*)(;)(".*>In order to stop receiving)
有人可以向我解释为什么第一条路线不起作用吗?基本上,为什么非捕获组仍然捕获其中的文本...
在你的第二个模式中,你使用了 3 个捕获组,你使用了你想要在替换中添加的样式,第 3 个组包含 In order to stop receiving
,它将在替换中使用第 3 个组后出现。
但是在你的第一个模式中,你使用了一个非捕获组 (?:
并且它将 匹配 但不是替换的一部分。
请注意,当使用像这样的非捕获组时,您完全可以省略它,因为像这样的分组本身没有例如量词或交替没有其他目的。
您可以为示例字符串使用模式,但这很容易出错,使用 DOM 解析器是更好的选择。
仅使用 2 个捕获组编写模式的方法:
(<td[^>]*\bstyle="[^"]*;)([^"]*">In order to stop receiving)
替换使用中:
font-size: 80%;
说明
(
捕获 组 1<td[^>]*
匹配<td
然后可选地重复除>
之外的任何字符
\bstyle="[^"]*;
匹配style="
然后可选地重复匹配除"
之外的任何字符,然后匹配最后一个分号(注意它现在是第 1 组的一部分)
)
关闭组 1(
捕获 第 2 组[^"]*">In order to stop receiving
可选择重复匹配除:
之外的任何字符,然后匹配">
后跟预期的文本
)
关闭组 2
看到一个regex demo。
另一种不使用捕获组编写模式的选项使用 \K
忘记到目前为止匹配的内容,并使用正向前瞻 (?=
断言右侧的预期文本:
<td[^>]*\bstyle="[^"]*;\K(?=[^"]*">In order to stop receiving)
再看一个regex demo。