2012-11-16 57 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

你说得对。我可能会集中这么多的用户友好,我忘却什么可操作的 –