Я работаю над небольшим фрагментом кода, воспроизводящим вкладки сонга, но я застрял в проблеме.
Мне нужно разобрать каждую линию вкладок песен и разделить ее, чтобы получить куски аккордов, с одной стороны, и слова в другом.
Каждый кусок был бы таким:
$line_chunk = array( 0 => //part of line containing one or several chords 1 => //part of line containing words );
Они должны оставаться «сгруппированными». Я имею в виду, что он должен расколоться только тогда, когда функция достигает «предела» между аккордами и словами.
Думаю, я должен использовать preg_split для достижения этого. Я сделал несколько тестов, но мне удалось разделить аккорды, а не «группы» аккордов:
$line_chunks = preg_split('/(\[[^]]*\])/', $line, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
Эти примеры показывают, что я хотел бы получить:
на строке, не содержащей аккордов:
$input = '{intro}'; $results = array( array( 0 => null, 1 => '{intro} ) );
на линии, содержащей только аккорды:
$input = '[C#] [Fm] [C#] [Fm] [C#] [Fm]'; $results = array( array( 0 => '[C#] [Fm] [C#] [Fm] [C#] [Fm]', 1 => null ) );
на строке, содержащей оба:
$input = '[C#]I'm looking for [Fm]you [G#]'; $results = array( array( 0 => '[C#]', 1 => 'I'm looking for' ), array( 0 => '[Fm]', 1 => 'you ' ), array( 0 => '[G#]', 1 => null ), );
Любые идеи о том, как это сделать?
Благодаря !
preg_split
– это не путь. В большинстве случаев, когда у вас есть сложная задача разделения, чтобы добиться этого, проще попытаться сопоставить то, что вас интересует, вместо того, чтобы пытаться разделить с помощью нелегкого определения разделителя.
Подход preg_match_all
:
$pattern = '~ \h* (?| # open a "branch reset group" ( \[ [^]]+ ] (?: \h* \[ [^]]+ ] )*+ ) # one or more chords in capture group 1 \h* ( [^[\n]* (?<=\S) ) # eventual lyrics (group 2) | # OR () # no chords (group 1) ( [^[\n]* [^\s[] ) # lyrics (group 2) ) # close the "branch reset group" ~x'; if (preg_match_all($pattern, $input, $matches, PREG_SET_ORDER)) { $result = array_map(function($i) { return [$i[1], $i[2]]; }, $matches); print_r($result); }
демонстрация
Группа сброса филиалов сохраняет ту же нумерацию групп для каждой ветви.
Примечание: не стесняйтесь добавлять:
if (empty($i[1])) $i[1] = null; if (empty($i[2])) $i[2] = null;
в функции карты, если вы хотите получить пустые элементы вместо пустых элементов.
Примечание2: если вы работаете по строкам, вы можете удалить \n
из шаблона.
Я бы пошел с PHP explode
:
/* * Process data */ $input = '[C#]I'm looking for [Fm]you [G#]'; $parts = explode("[", $input); $results = array(); foreach ($parts as $item) { $pieces = explode("]", $item); if (count($pieces) < 2) { $arrayitem = array( "Chord" => $pieces[0], "Lyric" => ""); } else { $arrayitem = array( "Chord" => $pieces[0], "Lyric" => $pieces[1]); } $results[] = $arrayitem; } /* * Echo results */ foreach ($results as $str) { echo "Chord: " . $str["Chord"]; echo "Lyric: " . $str["Lyric"]; }
Boudaries не тестируются в коде, а также в остальных пробелах, но это основа для работы.