$re = '/(?:\n{2,}|\A)
(?<table>
(?<table_header>
(?:
(?<th_single_col>(?&t_th_single_col))
|
(?<th_multi_col>(?&t_th_multi_col))
)
(?<table_header_sep>(?&t_th_sep))
){0,2}
(?<table_row>(?&t_row))+
(?<table_after>
\z
|
\n{2}
(?!
(?<next_table_header>
(?:
(?<next_th_single_col>(?&t_th_single_col))
|
(?<next_th_multi_col>(?&t_th_multi_col))
)
(?<next_table_header_sep>(?&t_th_sep))
){0,2}
(?<table_row>(?&t_row))
)
)
)
(?(DEFINE)
(?<t_th_single_col>
(?:
[ ]{0,3}
(?<t_th_start_pipe>\|)
[^\|\n]+?
\|?
\n
)
|
(?:
[^\|\n]+?
\|
\n
)
)
(?<t_th_multi_col>
(?:
[ ]{0,3}
(?:\| [^\|\n]+? \|{1,2})
(?:\|{0,2} [^\|\n]+? \|{0,2})+
\n
)
|
(?:
(?: [^\|\n]+ \|{1,2})
(?:\|{0,2} [^\|\n]+? \|{0,2})+
\n
)
)
(?<t_th_sep>
[\+\-\|][\-\|\+\: ]+\n
)
(?<t_row>
(?(<th_single_col>)
(?:
[ ]{0,3}
(?<tr_start_mark>[\|\:])?
(?<tr_col_content>.+?)
(?(<tr_start_mark>)[\|\:]?|[\|\:])
\n{1,2}
)
|
(?:
[ ]{0,3}
(?<tr_start_mark>[\|\:]+)?
(?<tr_col_content>.+?)
(?:
\|{1,2}
|
(?:
(?<=\s)\:{1,2}(?=\s+)
|
(?<=\s)\:{1,2}(?=\n)
)
)?
\n{1,2}
)+
)
)
)
/mxJ';
$str = '| | Grouping ||
+---------------+---------------------------------+
| First Header | Second Header | Third Header |
+---------------+-----------------+---------------+
| Content | *Long Cell* ||
: continued : ::
: content : ::
| Content | **Cell** | Cell |
: continued : : :
: content : : :
| New section | More | Data |
| And more | And more ||
';
preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);
// Print the entire match result
var_dump($matches);
Please keep in mind that these code samples are automatically generated and are not guaranteed to work. If you find any syntax errors, feel free to submit a bug report. For a full regex reference for PHP, please visit: http://php.net/manual/en/ref.pcre.php