0

我有一个 PHP 应用程序,它应该解析上传的文本文件,其格式类似于:

|                  |                |                  |
| -----------------------------------------------------|
| 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       |
| ---------------------------------------------------------------|

我需要做的基本上是以相同的顺序单独隔离每个“块”,这样我就可以一个一个地循环它们。一个“解决方案”可能正在做

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

但是,如果提交文本的人认为不必要的换行符不属于并删除它们,那么这将产生意想不到的结果。我尝试使用 preg_match_all(),但是自从我做任何真正的正则表达式以来已经有好几年了,所以我想不出一个可用的解决方案。

“块”的第一行总是包含 | 和空格,但字段可能包含文本。“块”的最后一行始终是一个管道,后跟一个空格,用破折号填充行,以 | 结尾。

4

3 回答 3

0

要匹配可选的换行符,请尝试使用'/\n(\n{1,})?/'. 这匹配第一个换行符,然后匹配任何附加行(如果存在)。

考虑到这一点,您的答案将是:

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

这将用换行符分割文本。

于 2012-11-16T01:52:41.473 回答
0

您的问题无法解决,因为您没有可靠的方法来区分块的法线与块的第一行或最后一行。

我完全赞成稳健性原则,但这是您只需要训练您的用户不要破坏数据的情况之一。您不能接受来自用户任意删除逗号的 CSV 格式数据,这里的场景基本相同。

于 2012-11-16T01:53:13.043 回答
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);

不过,我不确定这是否是最优雅甚至最可靠的方式,因为很难猜测内容到底是什么样子。

于 2012-11-16T02:48:36.413 回答