gpt4 book ai didi

php - 使用 PHP 从选项卡中提取和弦

转载 作者:可可西里 更新时间:2023-10-31 23:03:05 24 4
gpt4 key购买 nike

我正在努力弄清楚如何使用 preg_match_all 和 PREG_OFFSET_CAPTURE 解析音乐(文本)标签。

Example输入:

[D#] [G#] [Fm] 
[C#] [Fm] [C#] [Fm] [C#] [Fm]

[C]La la la la la la [Fm]la la la la [D#]

[Fm]I made this song Cause I [Bbm]love you
[C]I made this song just for [Fm]you [D#]
[Fm]I made this song deep in [Bbm]my heart

我想要得到的输出:

D# G# Fm 
C# Fm C# Fm C# Fm

C Fm D#
La la la la la la la la la la

Fm Bbm
I made this song Cause I love you

C Fm D#
I made this song just for you

Fm Bbm
I made this song deep in my heart

最后,我想用 html 标签包裹和弦。

请注意,和弦之间的空格应与原始输入中这些和弦的位置完全匹配。

我开始逐行解析输入,检测和弦,获取它们的位置,......但我的代码不起作用......我的函数 line_extract_chords 有问题,它无法正常工作。

有什么想法吗?

<style>
body{
font-family: monospace;
white-space: pre;
</style>

<?php

function parse_song($content){
$lines = explode(PHP_EOL, $content); //explode lines

foreach($lines as $key=>$line){
$chords_line = line_extract_chords($line);
$lines[$key] = implode("\n\r",(array)$chords_line);
}

return implode("\n\r",$lines);
}

function line_extract_chords($line){

$line_chords = null; //text line with chords, used to compute offsets
$line_chords_html = null; //line with chords links
$found_chords = array();

$line = html_entity_decode($line); //remove special characters (would make offset problems)

preg_match_all("/\[([^\]]*)\]/", $line, $matches, PREG_OFFSET_CAPTURE);

$chord_matches = array();

if ( $matches[1] ){
foreach($matches[1] as $key=>$chord_match){

$chord = $chord_match[0];


$position = $chord_match[1];
$offset= $position;
$offset-= 1; //left bracket
$offset-=strlen($line_chords); //already filled line

//previous matches
if ($found_chords){
$offset -= strlen(implode('',$found_chords));
$offset -= 2*(count($found_chords)); //brackets for previous chords
}

$chord_html = '<a href="#">'.$chord.'</a>';

//add spaces
if ($offset>0){
$line_chords.= str_repeat(" ", $offset);
$line_chords_html.= str_repeat(" ", $offset);
}

$line_chords.=$chord;
$line_chords_html.=$chord_html;
$found_chords[] = $chord;

}

}

$line = htmlentities($line); //revert html_entity_decode()

if ($line_chords){
$line = preg_replace('/\[([^\]]*)\]/', '', $line);
return array($line_chords_html,$line);
}else{
return $line;
}

}
?>

最佳答案

我想提出一个更简单的方法。它基于这样的假设,即输入数据实际上与您在此处描述的一样一般可解析。

<style>
.line{
font-family: monospace;
white-space: pre;
margin-bottom:0.75rem;
}

.group{
display: inline-block;
margin-right: 0.5rem;
}
.group .top,
.group .top{
display: block;
}
</style>
<?php

$input = "[D#] [G#] [Fm]
[C#] [Fm] [C#] [Fm] [C#] [Fm]

[C]La la la la la la [Fm]la la la la [D#]

[Fm]I made this song Cause I [Bbm]love you
[C]I made this song just for [Fm]you [D#]
[Fm]I made this song deep in [Bbm]my heart";

$output = '';

$inputLines = explode(PHP_EOL,$input);

foreach($inputLines as $line){
$output .='<div class="line">';

if (!strlen($line)){
$output .= '&nbsp;';
}
else{
$inputWords = explode(' ',$line);

foreach($inputWords as $word){
if (preg_match('/^\[(.+)\](.+)$/', $word, $parts)){
$output .='<span class="group"><span class="top">'.$parts[1].'</span><span class="bottom">'.$parts[2].'</span></span>';
}
elseif(preg_match('/^\[(.+)\]$/', $word, $parts)){
$output .='<span class="group"><span class="top">'.$parts[1].'</span><span class="bottom">&nbsp;</span></span>';
}
else{
$output .='<span class="group"><span class="top">&nbsp;</span><span class="bottom">'.$word.'</span></span>';
}
}
}

$output .='</div>';

}
die ($output);

这里做的事情很简单。该脚本仅通过将其包装在 HTML 中来赋予和弦数据意义。定位和表示是用 CSS 定义的。

它还表明您在将示例和弦转换为示例输出的方式上存在一点错误。 Fm D# 第 5 行似乎有一点偏差。至少我希望如此。

添加:

为什么您的代码不起作用。

确实如此。不起作用的是它的介绍。你数了一行中的字母,并在另一行中用空格替换了它。有两件事在这里不起作用:

  1. 在基本 HTML 中,多个连续的空格在浏览器 View 中减少为一个
  2. 通常任何浏览器的标准字体都不是等宽的。因此,没有简单的方法可以用相同宽度的空格替换字符。

那你会怎么做呢?

  1. 通过替换为不间断空格 ( ) 而不是简单的空格,您可以确保所有空格都实际显示在浏览器 View 中。正确地做到这一点意味着将 white-space: pre; 设置为一种样式,以便真正识别空白。
  2. 设置等宽字体 (font-family: monospace;) 以确保您的替换字体对齐。

就是这样:

<style>
body{
font-family: monospace;
white-space: pre;
</style>

<?php


function parse_song($content){
$lines = explode(PHP_EOL, $content); //explode lines

foreach($lines as $key=>$line){
$chords_line = line_extract_chords($line);
$lines[$key] = implode("\n\r",(array)$chords_line);
}

return implode("\n\r",$lines);
}

function line_extract_chords($line){

$line_chords = null; //text line with chords, used to compute offsets
$line_chords_html = null; //line with chords links
$found_chords = array();

$line = html_entity_decode($line); //remove special characters (would make offset problems)

preg_match_all("/\[([^\]]*)\]/", $line, $matches, PREG_OFFSET_CAPTURE);

$chord_matches = array();

if ( $matches[1] ){
foreach($matches[1] as $key=>$chord_match){

$chord = $chord_match[0];


$position = $chord_match[1];
$offset= $position;
$offset-= 1; //left bracket
$offset-=strlen($line_chords); //already filled line

//previous matches
if ($found_chords){
$offset -= strlen(implode('',$found_chords));
$offset -= 2*(count($found_chords)); //brackets for previous chords
}

$chord_html = '<a href="#">'.$chord.'</a>';

//add spaces
if ($offset>0){
$line_chords.= str_repeat(" ", $offset);
$line_chords_html.= str_repeat(" ", $offset);
}

$line_chords.=$chord;
$line_chords_html.=$chord_html;
$found_chords[] = $chord;

}

}

$line = htmlentities($line); //revert html_entity_decode()

if ($line_chords){
$line = preg_replace('/\[([^\]]*)\]/', '', $line);
return array($line_chords_html,$line);
}else{
return $line;
}

}

$input = "[D#] [G#] [Fm]
[C#] [Fm] [C#] [Fm] [C#] [Fm]

[C]La la la la la la [Fm]la la la la [D#]

[Fm]I made this song Cause I [Bbm]love you
[C]I made this song just for [Fm]you [D#]
[Fm]I made this song deep in [Bbm]my heart";



die(parse_song($input));

我删除了 self:: 引用以使其独立工作。

所以您实际上并没有在此处编写任何错误代码。你只是搞砸了结果的呈现。

尽管如此,您最终还是得到了一段毫无意义、几乎无法解析(可能是为了解释)的文本。解析输入的步骤应着重于赋予数据意义。例如,如果那是 HTML 或 XML 标记甚至 JSON 的方式,都没有关系。但是您应该将纯文本转换为结构化数据。

这样你就可以很容易地设计它。您可以识别整个结构的单个部分或过滤掉它们。

关于php - 使用 PHP 从选项卡中提取和弦,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33770714/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com