I've got a string like this:
####################
Section One
####################
Data A
Data B
####################
   Section Two
####################
Data C
Data D
etc.
I want to parse it into something like:
$arr(
    'Section One' => array('Data A', 'Data B'),
    'Section Two' => array('Data C', 'Data D')
)
At first I tried this:
$sections = preg_split("/(\r?\n)(\r?\n)#/", $file_content);
The problem is, the file isn't perfectly clean: sometimes there are different numbers of blank lines between the sections, or blank spaces between data rows.
The section head pattern itself seems to be relatively consistent:
####################
   Section Title
####################
The number of #'s is probably consistent, but I don't want to count on it. The white space on the title 开发者_开发技巧line is pretty random.
Once I have it split into sections, I think it'll be pretty straightforward, but any help writing a killer reg ex to get it there would be appreciated. (Or if there's a better approach than reg ex...)
I'd take a multi-step approach:
- split into section headings/content
- parse each heading/content pair into the desired array structure
Here's an example, split into multiple lines so you can track what is going on:
Note the lack of sanity checking, this assumes nice, neat heading/content groups. 
The regex was written for brevity and may or may not be sufficient for your needs.
// Split string on a line of text wrapped in lines of only #'s
$parts = preg_split('/^#+$\R(.+)\R^#+$/m', $subject, null, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
// Tidy up leading/trailing whitespace for each heading/content-block
$parts = array_map('trim', $parts);
// Chunk into array("heading", "content")
$parts = array_chunk($parts, 2);
// Create the final array
$sections = array();
foreach ($parts as $part) {
    $sections[$part[0]] = explode("\n", $part[1]);
}
// Lets take a look
var_dump($sections);
I was able to quickly wrote this up:
<?php
$text = <<<EOT
####################
Section One
####################
Data B.Thing=bar#
.##.#%#
####################
   Empty Section!
####################
####################
   Last section
####################
Blah
   Blah C# C# C#
EOT;
$entries = array_chunk(
   preg_split("/^#+/m", $text, null, PREG_SPLIT_NO_EMPTY),
   2
);
$sections = array();
foreach ($entries as $entry) {
  $key = trim($entry[0]);
  $value = preg_split("/\n/", $entry[1], null, PREG_SPLIT_NO_EMPTY);
  $sections[$key] = $value;
} 
print_r($sections);
?>
The output is: (as run on ideone.com)
Array
(
    [Section One] => Array
        (
            [0] => Data B.Thing=bar#
            [1] => .##.#%#
        )
    [Empty Section!] => Array
        (
        )
    [Last section] => Array
        (
            [0] => Blah
            [1] =>    Blah C# C# C#
        )
)
any help writing a killer reg ex to get it there would be appreciated
...I have your killer regex pattern -- it relies on the \G (continue) metacharacter to match the variably occurring lines of text after each section heading.
This technique is more optimal than previous answers because there is a single preg_ call and zero iterated function calls.
Sample Input:
$fileContents = <<<TEXT
####################
Section One
####################
Data A
Data B
####################
   Section Two
####################
Data C
Data D
Data E
####################
   Section Three
####################
Data F
TEXT;
Code: (Demo)
preg_match_all(
    '~(?:
        ^\#{3,}\R
        \h*(\S+(?:\h\S+)*)\h*\R
        \#{3,}
      |
        \G(?!\A)
      )
      \R
      (?!\#{3,})(.+)
     ~mx',
    $fileContents,
    $out,
    PREG_SET_ORDER
);
foreach ($out as $set) {
    $heading = $set[1] ?: $heading;
    $result[$heading][] = $set[2];
}
var_export($result ?? 'No qualifying data');
Output:
array (
  'Section One' => 
  array (
    0 => 'Data A',
    1 => 'Data B',
  ),
  'Section Two' => 
  array (
    0 => 'Data C',
    1 => 'Data D',
    2 => 'Data E',
  ),
  'Section Three' => 
  array (
    0 => 'Data F',
  ),
)
Breakdown:
~               #starting pattern delimiter
(?:             #start non-capturing group 1
  ^             #match the start of a line
  \#{3,}        #match 3 or more hash symbols
  \R            #match a newline sequence
  \h*           #match space or tab, zero or more times
  (             #start capture group 1
    \S+         #match one or more non-whitespace characters
    (?:         #start non-capturing group 2
      \h        #match space or tab
      \S+       #one or more non-whitespace characters
    )*          #end capture group 2, permit zero or more occurrences
  )             #end capture group 1
  \h*           #match space or tab, zero or more times
  \R            #match a newline sequence
  \#{3,}        #match 3 or more hash symbols
  |             #or
  \G(?!\A)      #continue matching but disallow starting from start of string
)               #end non-capturing group 1
\R              #match a newline sequence
(?!             #start negative lookahead
  \#{3,}        #match 3 or more hash symbols
)               #end negative lookahead
(.+)            #match the whole line excluding the trailing newline characters
~               #ending pattern delimiter
m               #pattern modifier: demand that ^ matches start of lines
x               #pattern modifier: allow meaningless whitespaces in pattern for improved readability
...this was a fun necropost.
 
         
                                         
                                         
                                         
                                        ![Interactive visualization of a graph in python [closed]](https://www.devze.com/res/2023/04-10/09/92d32fe8c0d22fb96bd6f6e8b7d1f457.gif) 
                                         
                                         
                                         
                                         加载中,请稍侯......
 加载中,请稍侯......
      
精彩评论