2012-11-16 55 views
0

的「塊」我是應該分析有類似這樣的格式上傳文本文件PHP應用程序:PHP PCRE匹配文本

|     |    |     | 
| -----------------------------------------------------| 
| Sample   | Data   |     | 
| -----------------------------------------------------| 
| Sample   | Data   |     | 
| -----------------------------------------------------| 
| Sample   | Data   |     | 
| -----------------------------------------------------| 


| Accepts     |       | 
| --------------------------------------------------------| 
| All      | Yes      | 
| --------------------------------------------------------| 
| More      | Yes      | 
| --------------------------------------------------------| 


|   |   | Years  |   |   | 
| ---------------------------------------------------------------| 
| 1998  | 1999  | 2000  | 2001  | 2002  | 
| ---------------------------------------------------------------| 
| 2003  | 2004  | 2005  | 2006  | 2007  | 
| ---------------------------------------------------------------| 
| 2008  | 2009  | 2010  | 2011  | 2012  | 
| ---------------------------------------------------------------| 

我需要做的基本上是隔離每個「阻止「自己以相同的順序,所以我可以循環他們一個接一個。 A「解決方案」可以做

preg_split("/\n{4,}/", $text); 

但是會產生unwated的結果,如果提交的文本的人決定了不必要的換行不屬於並刪除它們。我嘗試過使用preg_match_all(),但是自從我做了任何真正的正則表達式之後已經有很多年了,所以我無法想出一個可用的解決方案。

「塊」的第一行總是包含|和空格,但字段可能包含文本。 「塊」的最後一行始終是一個管道,後面跟着一個空格,破折號填充行,以|結尾。

+0

我想如果不能可靠地上' '/ \ N {2,} /''或'分裂 '/ \ N(\ S * \ n)的+ /'',則不能可靠地分離的。如果一個「表格」在下一個沒有空行的情況下出現,那麼也可能有兩個連續的表格具有相同的列號和寬度,在這種情況下,它們甚至可能無法被人工區分。 –

+0

如果有可靠的標題行,則可以檢測塊。但是你的樣本太抽象了。 – mario

+0

與標題沒有一致性,有些塊有標題,有些則沒有標題。內容是動態的(不同的集合,語言等),但塊的大小是恆定的。就像在上面的例子中那樣,這是確切的「預期」輸入。 –

回答

0

如果是文本文件的內容看起來像我會寫類似

$pat = '~ 
    (?<=^|\r{3}|\n{3}|(\r\n){3}) # beginning of string or following 3 newline chars 
     \|[ ]      # a pipe and a space 
     (
      [ \S]+      # 1 or more space or non space char 
      \|       # a pipe 
     )+       # 1 or more of this group 

     (\n|\r\n?)     # a newline 
     \|[ ]-+\|     # a pipe, a space, multiple dashes and a pipe 
     (\n|\r\n?)     # a newline 
     .*?       # anything between newlines above and below 
     (\n|\r\n?)     # a newline 
     \|[ ]-+\|     # a pipe, a space, multiple dashes and a pipe 
    (?=$|\r{3}|\n{3}|(\r\n){3})  # end of string or followed by 3 newline chars 
~sx'; 
preg_match_all($pat,$str,$res); 
$blocks = $res[0]; 
print_r($blocks); 

我不知道這是否是最優雅的,甚至可靠的方法,不過,因爲它很難猜猜看內容可能是什麼樣子。

+0

我一直在測試這種模式有各種可能的輸入數據,到目前爲止它做正是我一直在尋找!這次真是萬分感謝! –

+0

@ M.A。雖然我在質疑(即使在編寫模式時),但用戶輸入可能看起來與塊的最後部分看起來是否相同,從而打破了模式?在這種情況下,您可能想要在向後看和前瞻部分中擴展模式。這是,除非你在用戶輸入中轉義管道或將它們轉換成HTML實體。 – inhan

+0

輸入數據實際上是文件。雖然用戶可能會刪除不必要的換行符 - 而且他們確實有這些文件中出現的習慣 - 數據本身將保持不變。這些模塊遵循一系列規則,如果某些事情發生故障,這些規則會立即發出警告。我需要一種模式,根據塊的佈局(這是恆定的,不考慮寬度和高度),而不是例如多個換行符來確保塊被隔離。 –

0

要匹配可選換行符,請嘗試使用'/\n(\n{1,})?/'。這匹配第一個換行符,然後匹配任何額外的行(如果存在)。

考慮到這一點,你的答案是:

preg_split("/\n(\n{1,})?/", $text)

這將按新行分割文本。

0

你的問題是不可能解決的,因爲你沒有可靠的方法來區分塊的法線和塊的第一行或最後一行。

我全部都是爲robustness principle,但這是您只需要訓練用戶不要破壞數據的情況之一。您無法接受任意刪除逗號的用戶的CSV格式數據,這裏的情況基本相同。

+0

你說得對。我可能會集中這麼多的用戶友好,我忘卻什麼可操作的 –