2010-06-23 34 views
0

我已經在PHP中創建了一個簡單的模板「引擎」來將PHP生成的數據替換爲HTML頁面。下面是它如何工作的:PHP - 我需要一些幫助我的正則表達式

我主要的模板文件,我有變量,像這樣:

<title><!-- %{title}% --></title> 

我然後將數據分配到這些變量的主要頁面加載

$assign = array (
    'title' => 'my website - ' 
); 

然後,我有爲內容頁面加載單獨的模板塊。以上只是處理頁眉和頁腳。在這些「內容模板文件」中的一個,我有變量,像這樣:

<!-- %{title=content page}% --> 

一旦得到執行,主要的模板數據進行編輯,包括頁面內容變量導致:

<title>my website - content page</title> 

爲此,它會用下面的代碼:

if (preg_match('/<!-- %{title=\s*(.*?)}% -->/s', $string, $matches)) { 
    // Find variable names in the form of %{varName=new data to append}% 
    // If found, append that new data to the exisiting data 
    $string  = preg_replace('/<!-- %{title=\s*(.*?)}% -->/s', null, $string); 
    $varData[$i] .= $matches[1]; 
} 

這基本上消除了模板變量,然後將可變數據分配給現有變量。現在,這一切都很好。我遇到的問題是嵌套模板變量。如果我這樣做:

<!-- %{title=content page (author: <!-- %{name}% -->) --> 

該模式有時會弄亂每個變量的開始和結束標記。

如何修復我的正則表達式以防止出現這種情況?

謝謝。

回答

4

答案是你不要這樣做與正則表達式。正則表達式是一種常規語言。當你開始嵌套時,它不再是普通的語言。它至少是一種上下文無關的語言(「CFL」)。 CFLs只能被處理(假設他們毫不含糊)。

具體來說,常規語言可以用有限狀態機(「FSM」)表示。 CFL需要下推自動機(「PDA」)。

區別的一個例子是嵌套的標籤HTML:

<div> 
    <div>inner</div> 
</div> 

我的建議是不要寫你自己的模板語言。那已經完成了。多次。使用Smarty或Zend,Kohana或其他軟件。如果你真的寫自己的話,那就正確地做。解析它。

+0

我對正則表達式並不是很滿意,所以如果你能推薦一個替代方案,那麼我就是全力以赴。我還能如何完成我在做的事情? – dave 2010-06-23 01:30:29

0

如果你問我認爲你在問什麼,那實際上是不可能的。如果我正確地閱讀你的問題,你想匹配任意嵌套的<!-- ... -->序列與內部的特定事物。不幸的是,正則表達式只能匹配特定類型的字符串;任何正則表達式只能匹配regular language。一個知名的語言是而非經常是language of balanced parentheses (also known as the the Dyck language),這正是你想要匹配的。爲了匹配任意嵌套的註釋字符串,您需要一個更強大的工具。我相當確定有預先存在的PHP模板引擎;你可以看看其中的一個。

+0

用單個語句做這件事可能是不可能的(雖然我不是100%確定我買了那個),但它當然可以遞歸地或迭代地完成。當涉及PHP(或支持它們的任何語言)時,正則表達式變得比它們孤立的功能強大得多。 – Andrew 2010-06-23 01:58:29

0

要解決你的問題,你應該

  • preg_match_all()取代preg_match();
  • 找到模式,並將它們從最後一個替換爲第一個;
  • 使用更具限制性的模式,如'/<!-- %{title=\s*([^}]*?)}% -->/s'
0

我在過去做過類似的事情,而且我遇到過相同的嵌套問題。在你的情況下,我會做的是重複搜索你的文本的匹配(而不是搜索一次,並循環通過匹配),並提取所需的字符串搜索任何不包括您的關閉字符串。

在你的情況下,它可能會是這樣的:

/(<!--([^(-->)]*?)-->)/ 

的正則表達式像這樣的一場噩夢來解釋,但基本上,([^(-->)]*)會發現,不包括您的結束標記任何字符串(姑且稱之爲即AAA)。它將位於匹配組中,該組本身就是您的模板標籤,(<!--AAA-->)

我確信這種模板方法是做錯事情的錯誤方式,但我從來不知道做得更好。 ASP和ColdFusion總是困擾着我,你必須將你的腳本標籤嵌入到HTML中,當我開始自己做時,我認爲這是個人失敗。

我現在所做的大多數正則表達式都是用JavaScript編寫的,所以我可能會錯過一些PHP通過Perl獲得的真棒細微差別。如果有人能夠更清楚地寫出這些,我會很高興。

1

你爲什麼要滾動你自己的模板引擎?如果你想要這種複雜性,有很多地方已經爲它提供瞭解決方案。你應該插入Smarty或類似的東西。

0

我也曾經遇到過這個問題,雖然我沒有使用正則表達式。

如果您在語法上使用strrpos(PHP5 +)從右到左搜索開頭標記<!-- %{,然後向前搜索第一個出現的下一個結束標記,然後先替換該塊,您將最終首先替換最內部的嵌套變量。這應該可以解決您的問題。

您也可以以相反的方式進行操作,找到第一個出現的結束標記,然後向後找到相應的開始標記。