在X段之后注入代码但避免使用表

时间:2014-04-20 08:44:03

标签: php regex explode

我想在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>,那么如何避免这种情况?

由于

2 个答案:

答案 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[^>]*>).
         |
            (?&paragraph)
         )*
      </p\s*>
   )
)
(?&table)(*SKIP)(*FAIL)           # Let's skip table tags
|
(?&paragraph)                     # 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)

编辑:昨晚已经很晚了。

  1. PREG_SPLIT_DELIM_CAPTURE很整洁但我现在添加了更好的主意(方法1)。

  2. 还改进了方法2,用更快strstr

  3. 替换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_splitPREG_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_DELIM_CAPTURE

    这是一个关于preg_split如何工作的演示:

    $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] => )

    在这个例子中看看如何保留分隔符(@序列)?你已经手术隔离了它们但没有丢失它们,所以你可以处理其他字符串,然后将所有东西重新组合在一起。