php
  • regex
  • explode
  • 2014-04-20 51 views 4 likes 
    4

    我想在X段落之後注入一些代碼,這對於php來說非常簡單。在X段落後注入代碼但避免表格

    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

    不與正則表達式 – Valerij

    +0

    解析HTML如果你看到原來簡短的回答,我大大擴大了,但現在得走了。 :) – zx81

    +2

    @oscar我添加了方法1,比昨天的方法更好。這個想法喚醒了我,現在看起來哈姆扎有一個類似的想法使用(* SKIP)(* FAIL),但是通過一瞥它不是同一個想法 - 也許更加緊湊,將詳細閱讀Hamza的想法現在。 – zx81

    回答

    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

    參考文獻:

    +0

    WTF! O.O太棒了! –

    +2

    好主意!我一直喜歡你的工作。帶有(* SKIP)(* FAIL)的preg_replace_callback的想法喚醒了我,並且在查看您的答案之前,我已經將其添加到了我的解決方案中。但它與你的答案看起來很不一樣,我現在將詳細閱讀。 – zx81

    +0

    ,它的工作! –

    2

    編輯:這是昨天深夜。

    1. PREG_SPLIT_DELIM_CAPTURE整齊,但我現在添加一個更好的主意(方法1)。

    2. 也有所改善方法2與更快的substr

    方法1更換strstrpreg_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); 
    

    短得多!

    而這裏的$正則表達式演示向您展示它是如何匹配不包含表的元素。

    $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沒有很好地形成和$表中數據的中間開始,全盤皆輸。如果這是一個問題,讓我知道,我們可以在正則表達式上工作。

    方法2

    這裏是一個浮現在腦海的第一個解決方案。

    總之,我會考慮使用preg_splitPREG_SPLIT_DELIM_CAPTURE標誌。

    其基本思想是使用特殊的preg_split來隔離表格,並對可證明無表格的元素進行注射。

    A.第1步:您的分隔符將是一個全表順序:從<table</table>

    這與正則表達式模式指定如(?s)<table.*?</table>

    注意,我是一個分隔符實現使用一個不尋常的分隔符分割$data如果你在那裏上課,不要關閉<table

    所以,你必須像

    $tableseparator = preg_split("~(?s)(<table.*?</table>)~", $data, -1, PREG_SPLIT_DELIM_CAPTURE); 
    

    這個PREG_SPLIT_DELIM_CAPTURE標誌的好處是,整個分隔符,這是我們捕捉由於在正則表達式的括號,成爲數組中的元素,讓我們可以隔離表而不會丟失它們。 [見底部的演示。]這樣,你的字符串被分解爲乾淨的「無表格」和「表格」部分。

    B.步驟2:迭代$ tableseparator元素。對於每一個元素,做一個

    if(substr($tableseparator[$i],0,6)=="<table")

    如果<table發現,先不談元(不注射)。如果找不到,那個元素就乾乾淨淨了,你可以用它來執行你的inject()魔法。

    C.步驟3:$tableseparator的元素重新組合在一起(內爆就像您在inject函數中一樣)。

    所以,你有兩個級別的爆炸和內爆,先用使preg_split,第二你的爆炸!

    對不起,我沒有時間來編寫所有的細節,但我敢肯定,你自己看着辦吧。 :)

    preg_splitPREG_SPLIT_DELIM_CAPTURE演示

    這裏的使preg_split是如何工作的一個演示:

    $text = "[email protected]@@[email protected]@@@"; 
    $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] =>)

    查看如何在這個例子中,分隔符( @序列)被保存了嗎?你通過手術將他們隔離但不會丟失它們,所以你可以在其他字符串上工作,然後把所有的東西放在一起。

    +0

    很好!我絕對要試試 –

    +2

    @OscarFanelli感謝您的評論。它瘋了!我用(* SKIP)(* FAIL)喚醒了preg_replace_callback的這個想法,並對此激烈地工作,並看到強大的Hamza之前已經發布了一個短的。但答案看起來很不一樣,所以現在你有一個組合可以選擇你的代碼。 :) – zx81

    +0

    是的,兩個都很好! –

    相關問題