使用 preg_split 拆分和弦和单词
use preg_split to split chords and words
我正在编写一小段播放处理歌曲标签的代码,但我遇到了一个问题。
一方面我需要解析每首歌曲的标签行并将其拆分以获得 chords 的块,另一方面 words另一个。
每个块都像:
$line_chunk = array(
0 => //part of line containing one or several chords
1 => //part of line containing words
);
他们应该留下 "grouped"。我的意思是只有当函数达到和弦和单词之间的 "limit" 时才应该拆分。
我想我应该使用preg_split来实现这个。我做了一些测试,但我只能在和弦上拆分,而不是 "groups" 和弦:
$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
),
);
关于如何执行此操作的任何想法?
谢谢!
我会选择 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"];
}
代码中没有测试边界以及剩余的空格,但它是工作的基础。
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;
如果你想获取空项而不是空项,请在 map 函数中。
注意 2:如果逐行工作,可以从模式中删除 \n
。
我正在编写一小段播放处理歌曲标签的代码,但我遇到了一个问题。
一方面我需要解析每首歌曲的标签行并将其拆分以获得 chords 的块,另一方面 words另一个。
每个块都像:
$line_chunk = array(
0 => //part of line containing one or several chords
1 => //part of line containing words
);
他们应该留下 "grouped"。我的意思是只有当函数达到和弦和单词之间的 "limit" 时才应该拆分。
我想我应该使用preg_split来实现这个。我做了一些测试,但我只能在和弦上拆分,而不是 "groups" 和弦:
$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
),
);
关于如何执行此操作的任何想法?
谢谢!
我会选择 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"];
}
代码中没有测试边界以及剩余的空格,但它是工作的基础。
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;
如果你想获取空项而不是空项,请在 map 函数中。
注意 2:如果逐行工作,可以从模式中删除 \n
。