2015-12-16 13 views
6

Pracuję nad małym kawałkiem kodu obsługującym obsługę zakładek, ale utknąłem na problemie.Używanie preg_split do dzielenia akordów i słów

muszę analizować każdą linię kartę piosenkę i podzielić ją dostać Kawałki akordów z jednej strony, a słowy w drugiej.

Każdy kawałek będzie jak:

$line_chunk = array(
    0 => //part of line containing one or several chords 
    1 => //part of line containing words 
); 

one powinny pozostać "zgrupowane". Rozumiem przez to, że powinno się dzielić tylko wtedy, gdy funkcja osiągnie "granicę" między akordami i słowami.

Chyba powinienem użyć preg_split, aby to osiągnąć. Zrobiłem kilka testów, ale udało mi się tylko podzielić na akordy, a nie „grup” akordów:

$line_chunks = preg_split('/(\[[^]]*\])/', $line, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); 

tych przykładów pokazuje, co chciałbym dostać:

na linii zawierającej Brak akordy:

$input = '{intro}'; 

$results = array(
    array(
     0 => null, 
     1 => '{intro} 
    ) 
); 

na linii zawierające tylko akordy:

$input = '[C#] [Fm] [C#] [Fm] [C#] [Fm]'; 

$results = array(
    array(
     0 => '[C#] [Fm] [C#] [Fm] [C#] [Fm]', 
     1 => null 
    ) 
); 

na linii zawierające zarówno:

$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 
    ), 
); 

Wszelkie pomysły, jak to zrobić?

Dzięki!

Odpowiedz

1

preg_split to nie jest droga. W większości przypadków, gdy masz do wykonania skomplikowane podzielone zadanie, łatwiej jest spróbować dopasować to, co cię interesuje, zamiast próbować podzielić z niełatwo zdefiniować separator.

preg_match_all podejście:

$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); 
} 

demo

Grupa zresetowane oddział zachowuje tę samą grupę numeracji dla każdego oddziału.

Uwaga: nie krępuj się dodać:

if (empty($i[1])) $i[1] = null;  
if (empty($i[2])) $i[2] = null; 

w funkcji mapy, jeśli chcesz uzyskać zerowe przedmioty zamiast pustych elementów.

Uwaga 2: jeśli pracujesz linia po linii, możesz usunąć \n ze wzoru.

0

pójdę z 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 nie są testowane w kodzie, a także pozostałe odstępy, ale jest to podstawa do pracy.

Powiązane problemy