我想在X段后注入一些代码,这对于php来说非常简单。
public function inject($text, $paragraph = 2) {
$exploded = explode("</p>", $text);
if (isset($exploded[$paragraph])) {
$exploded[$paragraph] = '
MYCODE
' . $exploded[$paragraph];
return implode("</p>", $exploded);
}
return $text;
}
但是,我不想在$text
内注入我的<table>
,那么如何避免这种情况?
由于
答案 0 :(得分:3)
我有时候有点疯狂,有时我会选择懒惰的模式,但这次我会选择朦胧的东西。
$input = 'test <table><p>wuuut</p><table><p>lolwut</p></table></table> <p>foo bar</p> test1 <p>baz qux</p> test3'; # Some input
$insertAfter = 2; # Insert after N p tags
$code = 'CODE'; # The code we want to insert
$regex = <<<'regex'
~
# let's define something
(?(DEFINE)
(?P<table> # To match nested table tags
<table\b[^>]*>
(?:
(?!</?table\b[^>]*>).
|
(?&table)
)*
</table\s*>
)
(?P<paragraph> # To match nested p tags
<p\b[^>]*>
(?:
(?!</?p\b[^>]*>).
|
(?¶graph)
)*
</p\s*>
)
)
(?&table)(*SKIP)(*FAIL) # Let's skip table tags
|
(?¶graph) # And match p tags
~xsi
regex;
$output = preg_replace_callback($regex, function($m)use($insertAfter, $code){
static $counter = 0; # A counter
$counter++;
if($counter === $insertAfter){ # Should I explain?
return $m[0] . $code;
}else{
return $m[0];
}
}, $input);
var_dump($output); # Let's see what we've got
Online regex demo Online php demo
<强>参考文献:强>
答案 1 :(得分:2)
编辑:昨晚已经很晚了。
PREG_SPLIT_DELIM_CAPTURE
很整洁但我现在添加了更好的主意(方法1)。
还改进了方法2,用更快strstr
substr
醇>
方法1:preg_replace_callback
(*SKIP)(*FAIL)
(更好)
让我们使用对inject
函数的回调直接替换可证明无表格的文本。
这是一个匹配无表格文本的正则表达式:
$regex = "~(?si)(?!<table>).*?(?=<table|</table)|<table.*?</table>(*SKIP)(*FAIL)~";
简而言之,这可以匹配完整非表格的文本或匹配完整的表格而失败。
以下是您的替代人选:
$injectedString = preg_replace_callback($regex,
function($m){return inject($text,$m[0]);},
$data);
更短!
这是一个$ regex的演示,向您展示它如何与不包含表格的元素相匹配。
$text = "<table> to
</table>not a table # 1<table> to
</table>NOT A TABLE # 2<table> to
</table>";
$regex = "~(?si)(?!<table>).*?(?=<table|</table)|<table.*?</table>(*SKIP)(*FAIL)~";
$a = preg_match_all($regex,$text,$m);
print_r($m);
输出: Array ( [0] => Array ( [0] => not a table # 1 [1] => NOT A TABLE # 2 ) )
当然html没有很好地形成,$ data从表中间开始,所有的赌注都关闭了。如果这是一个问题让我知道,我们可以处理正则表达式。
方法2
这是我想到的第一个解决方案。
简而言之,我会考虑将preg_split
与PREG_SPLIT_DELIM_CAPTURE
标志一起使用。
基本思想是使用特殊的preg_split
隔离表,并对可证明无表格的元素执行注入。
:一种。第1步:使用不常见的分隔符拆分$data
:您的分隔符将是一个完整的表序列:从<table
到</table>
这是通过正则表达式模式指定的分隔符实现的,例如(?s)<table.*?</table>
请注意,如果您有课程,我不会关闭<table
。
所以你有类似
的东西$tableseparator = preg_split( "~(?s)(<table.*?</table>)~", $data, -1, PREG_SPLIT_DELIM_CAPTURE );
这个PREG_SPLIT_DELIM_CAPTURE
标志的好处是,由于正则表达式模式中的括号,我们捕获的整个分隔符成为数组中的元素,因此我们可以隔离表而不会丢失它们。 [请参阅底部的演示。]这样,您的字符串就会被分解成干净的表格。和&#34;是一张桌子&#34;件。
<强> B中。第2步:迭代$ tableseparator元素。对于每个元素,请执行
if(substr($tableseparator[$i],0,6)=="<table")
如果找到<table
,请单独保留元素(不要注入)。如果找不到,那个元素就干净了,你可以在它上面做inject()
魔法。
<强>℃。第3步:将$tableseparator
的元素重新组合在一起(就像在inject
函数中一样崩溃)。
所以你有两级爆炸和内爆,首先是preg_split,第二次爆炸!
很抱歉,我没有时间对所有内容进行详细编码,但我确定您可以解决这个问题。 :)
带有preg_split
演示 的 这是一个关于preg_split如何工作的演示: 输出: 在这个例子中看看如何保留分隔符(@序列)?你已经手术隔离了它们但没有丢失它们,所以你可以处理其他字符串,然后将所有东西重新组合在一起。PREG_SPLIT_DELIM_CAPTURE
$text = "Hi@There@@Oscar@@@@";
$regex = "~(@+)~";
$a = preg_split($regex,$text,-1,PREG_SPLIT_DELIM_CAPTURE);
print_r($a);
Array ( [0] => Hi [1] => @ [2] => There [3] => @@ [4] => Oscar [5] => @@@@ [6] => )