2017-08-16 41 views
-2

我期待刪除PHP中的BBCode作出引號,像這樣的例子:如何從文本中刪除特定用戶的所有bbcode引用塊?

[quote=testuser] 
[quote=anotheruser]a sdasdsa dfv rdfgrgre gzdf vrdg[/quote] 
sdfsd fdsf dsf sdf[/quote] 
the rest of the post text 

我期待在做一個阻塞系統,所以用戶不必看那些他們不」內容不想要。所以說「testuser」被封鎖了,他們不希望整個引用部分,包括嵌套在裏面的第二個引用,因爲這是主引用的一部分。

所以職位將只剩下:

後文

我想知道的最佳方式的其餘部分做這個。我希望正則表達式,但它更復雜,我想,我有這樣的嘗試:

/\[quote\=testuser\](.*)\[\/quote\]/is 

然而,然後捕獲所有最終報價標記。

是否有另一種方法是快速的,或者是我的正則表達式的一個很好的解決方法?

總結:刪除被阻止用戶的初始報價以及該報價中的所有內容,但除此之外沒有其他內容。

+0

既然有能力巢報價,你是不是要能夠讓你獨自一人要與正則表達式的確切功能。沒有辦法跟蹤你已經通過了多少[quote = ...]。 – digitaLink

+0

試試這個'(\ [quote =)(。*?)]((\ s | \ S)*?(\ [\/quote \]))*'因爲只有第一個引號和最後一個引號是幾乎所有的事情。如果您使用替代,組2('$ 2')等於第一個引號用戶名。 https://regex101.com/r/0pkmgl/2 – GrumpyCrouton

+0

你能寫出你想要隱藏的東西嗎?或寫出你想看到的出來 –

回答

1

據我所知,這不是一個簡單的過程。這裏是我的步驟...

  1. 使用preg_split()來劃分輸入字符串3種方式:打開報價標籤,關閉報價標籤和其他。我正在拆分開始和結束標記,但使用DELIM_CAPTURE將它們保留在輸出數組中並保留原始位置/順序。使用NO_EMPTY以便在foreach循環中沒有無用的迭代。
  2. 循環遍歷生成的數組並搜索用戶名稱以省略。
  3. 當發現由所述目標用戶報價,存儲元件的起始索引,並設置$open爲1
  4. 每當一個新的開引號標記發現$open遞增。
  5. 每當發現新的結束標記標記$open遞減。
  6. 只要$open達到0,$startend索引被送到range()生成一個數組填充兩點之間的數字。
  7. array_flip(),當然,將值移到鍵。
  8. array_diff_key()刪除由preg_split()生成的數組中的點的範圍。
  9. 如果一切順利,implode()會將子串重新粘合在一起,只保留所需的組件。

代碼:(Demo

/* 
This function DOES NOT validate the $bbcode string to contain a balanced number of opening & closing tags. 
This funcion DOES check that there are enough closing tags to conclude a targeted opening tag. 
*/ 
function omit_user_quotes($bbcode,$user){ 
    $substrings=preg_split('~(\[/?quote[^]]*\])~',$bbcode,NULL,PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY); 
    $opens=0; // necessary declaration to avoid Notice when no quote tags in $bbcode string 
    foreach($substrings as $index=>$substring){ 
     if(!isset($start) && $substring=="[quote={$user}]"){ // found targeted user's first opening quote 
      $start=$index; // disqualify the first if statement and start searching for end tag 
      $opens=1; // $opens counts how many end tags are required to conclude quote block 
     }elseif(isset($start)){ 
      if(strpos($substring,'[quote=')!==false){ // if a nested opening quote tag is found 
       ++$opens; // increment and continue looking for closing quote tags 
      }elseif(strpos($substring,'[/quote]')!==false){ // if a closing quote tag is found 
       --$opens; // decrement and check for quote tag conclusion or error 
       if(!$opens){ // if $opens is zero ($opens can never be less than zero) 
        $substrings=array_diff_key($substrings,array_flip(range($start,$index))); // slice away unwanted elements from input array 
        unset($start); // re-qualify the first if statement to allow the process to repeat 
       } 
      } 
     } 
    } 
    if($opens){ // if $opens is positive 
     return 'Error due to opening/closing tag imbalance (too few end tags)'; 
    }else{ 
     return trim(implode($substrings)); // trims the whitespaces on either side of $bbcode string as feature 
    }  
} 

/* Single unwanted quote with nested innocent quote: */ 
/*$bbcode='[quote=testuser] 
[quote=anotheruser]a sdasdsa dfv rdfgrgre gzdf vrdg[/quote] 
sdfsd fdsf dsf sdf[/quote] 
the rest of the test'; */ 
/* output: the rest of the test */ 

/* Complex battery of unwanted, wanted, and nested quotes: */ 
$bbcode='[quote=mickmackusa]Keep this[/quote] 
[quote=testuser]Don\'t keep this because 
    [quote=mickmackusa]said don\'t do it[/quote] 
    ... like that\'s a good reason 
    [quote=NaughtySquid] It\'s tricky business, no?[/quote] 
    [quote=nester][quote=nesty][quote=nested][/quote][/quote][/quote] 
[/quote] 
Let\'s remove a second set of quotes 
[quote=testuser]Another quote block[/quote] 
[quote=mickmackusa]Let\'s do a third quote inside of my quote... 
[quote=testuser]Another quote block[/quote] 
[/quote] 
This should be good, but 
What if [quote=testuser]quotes himself [quote=testuser] inside of his own[/quote] quote[/quote]?'; 
/* output: [quote=mickmackusa]Keep this[/quote] 

Let's remove a second set of quotes 

[quote=mickmackusa]Let's do a third quote inside of my quote... 

[/quote] 
This should be good, but 
What if ? */ 

/* No quotes: */ 
//$bbcode='This has no bbcode quote tags in it.'; 
/* output: This has no bbcode quote tags in it. */ 

/* Too few end quote tags by innocent user: 
(No flag is raised because the targeted user has not quoted any text) */ 
//$bbcode='This [quote=mickmackusa] has not end tag.'; 
/* output: This [quote=mickmackusa] has not end tag. */ 

/* Too few end quote tags by unwanted user: */ 
//$bbcode='This [quote=testuser] has not end tag.'; 
/* output: Error due to opening/closing tag imbalance (too few end tags) */ 

/* Too many end quote tags by unwanted user: 
(No flag is raised because the function does not validate the bbcode text as fully balanced) */ 
//$bbcode='This [quote=testuser] has too many end[/quote] tags.[/quote]'; 
/* output: This tags.[/quote] */ 

$user='testuser'; 

echo omit_user_quotes($bbcode,$user); // omit a single user's quote blocks 

/* Or if you want to omit quote blocks from multiple users, you can use a loop: 
$users=['mickmackusa','NaughtySquid']; 
foreach($users as $user){ 
    $bbcode=omit_user_quotes($bbcode,$user); 
} 
echo $bbcode; 
*/ 
+0

在添加解釋之前,我需要做一些更多的測試。 – mickmackusa

+0

所有幫助表示讚賞:) – NaughtySquid

+0

@NaughtySquid現在我對它很有信心。 – mickmackusa

1

你想要的是一個正則表達式不可能的。我會建議掃描文件,直到找到[quote=testuser]。找到它後,設置一個布爾值以開始過濾,並將計數器設置爲1.在布爾值爲true後,爲每個[quote=...]標記遞增計數器。每遇到一個[/quote]標籤,減少計數器。當計數器達到0時,將用於過濾的布爾值更改爲false。

這是一些sudocode。您可能需要根據您的應用程序對其進行修改,但我認爲它顯示了使用的一般算法。

filtering = false 
counter = 0 
for each line: 
    if line contains "[quote=testuser]" 
     filtering = true 
     counter = 0 
    if line contains "[quote=" 
     counter += 1 
    if line contains "[/quote] 
     counter -= 1 
    if counter = 0 
     filtering = false 
    if not filtering 
     print line 
+0

這聽起來像希望正確的軌道,是否有一個例子在某種地方這樣的技術? – NaughtySquid

+0

我會盡量寫一個簡單的例子或看看我能不能找到一個 – digitaLink

+0

你是明星謝謝你! – NaughtySquid

相關問題