Вот регулярное выражение решения проблемы.Имейте в виду, что вам не нужно регулярное выражение здесь.См. Второй вариант ниже.
<?php
$string = '"Stranglehold"
Written by Ted Nugent
Performed by Ted Nugent
Courtesy of Epic Records
By Arrangement with
Sony Music Licensing
"Chateau Lafltte \'59 Boogie"
Written by David Peverett
and Rod Price
Performed by Foghat
Courtesy of Rhino Entertainment
Company and Bearsville Records
By Arrangement with
Warner Special Products';
// Titles delimit a record
$title_pattern = '#"(?<title>[^\n]+)"\n(?<meta>.*?)(?=\n"|$)#s';
// From the meta section we need these tokens
$meta_keys = array(
'Written by ' => 'written',
'Performed by ' => 'performed',
'Courtesy of ' => 'courtesy',
"By Arrangement with\n" => 'arranged',
);
$meta_pattern = '#(?<key>' . join(array_keys($meta_keys), "|") . ')(?<value>[^\n$]+)(?:\n|$)#ims';
$songs = array();
if (preg_match_all($title_pattern, $string, $matches, PREG_SET_ORDER)) {
foreach ($matches as $match) {
$t = array(
'title' => $match['title'],
);
if (preg_match_all($meta_pattern, $match['meta'], $_matches, PREG_SET_ORDER)) {
foreach ($_matches as $_match) {
$k = $meta_keys[$_match['key']];
$t[$k] = $_match['value'];
}
}
$songs[] = $t;
}
}
приведет к
$songs = array (
array (
'title' => 'Stranglehold',
'written' => 'Ted Nugent',
'performed' => 'Ted Nugent',
'courtesy' => 'Epic Records',
'arranged' => 'Sony Music Licensing',
),
array (
'title' => 'Chateau Lafltte \'59 Boogie',
'written' => 'David Peverett',
'performed' => 'Foghat',
'courtesy' => 'Rhino Entertainment',
'arranged' => 'Warner Special Products',
),
);
Также возможно решение без регулярных выражений, хотя и несколько более подробное:
<?php
$string = '"Stranglehold"
Written by Ted Nugent
Performed by Ted Nugent
Courtesy of Epic Records
By Arrangement with
Sony Music Licensing
"Chateau Lafltte \'59 Boogie"
Written by David Peverett
and Rod Price
Performed by Foghat
Courtesy of Rhino Entertainment
Company and Bearsville Records
By Arrangement with
Warner Special Products';
$songs = array();
$current = array();
$lines = explode("\n", $string);
// can't use foreach if we want to extract "By Arrangement"
// cause it spans two lines
for ($i = 0, $_length = count($lines); $i < $_length; $i++) {
$line = $lines[$i];
$length = strlen($line); // might want to use mb_strlen()
// if line is enclosed in " it's a title
if ($line[0] == '"' && $line[$length - 1] == '"') {
if ($current) {
$songs[] = $current;
}
$current = array(
'title' => substr($line, 1, $length - 2),
);
continue;
}
$meta_keys = array(
'By Arrangement with' => 'arranged',
);
foreach ($meta_keys as $key => $k) {
if ($key == $line) {
$i++;
$current[$k] = $lines[$i];
continue;
}
}
$meta_keys = array(
'Written by ' => 'written',
'Performed by ' => 'performed',
'Courtesy of ' => 'courtesy',
);
foreach ($meta_keys as $key => $k) {
if (strpos($line, $key) === 0) {
$current[$k] = substr($line, strlen($key));
continue 2;
}
}
}
if ($current) {
$songs[] = $current;
}