【问题标题】:Regex parsing chords正则表达式解析和弦
【发布时间】:2022-01-25 03:18:11
【问题描述】:

我在 SO 的另一篇文章中发现了这个正则表达式

\b(\(*[CDEFGAB](?:b|bb)*(?:\+|#|##|dim|sus|maj|min|aug|m|M|°|[0-9])*[\(]?[\d\/]*[\)]?(?:[CDEFGAB](?:b|bb)*(?:#|##|dim|sus|maj|min|aug|m|M|°|[0-9])*[\d\/]*)*\)*)\b

当我将它与preg_replace 一起使用时,这个正则表达式效果很好,但是当它找到A# B# C# D# E# E# F# G# 时(不跟m 类似G#m,在这种情况下 G#m 工作得很好)。

例如,当我在preg_replace($regex, '<span class="_c">$1</span>', $lyrics) 中使用正则表达式时,以下歌词将突出显示FG#m

F#
Angel eyes,
G#m
Why won’t you let me apologise?

我被卡住了,而且不太擅长正则表达式。任何帮助,将不胜感激。 提前致谢

【问题讨论】:

  • 对不起,我对音乐一无所知。应该发生什么?是# 匹配为非单词边界的问题吗?

标签: php regex


【解决方案1】:

你可以使用adaptive dynamic word boundaries:

$lyrics = "F#\nAngel eyes,\nG#m\nWhy won’t you let me apologise?";
$regex = '/(?:\b(?=\w)|\B(?!\w))\(*\b[CDEFGAB](?:b|bb)*(?:\+|\#{1,2}|dim|sus|maj|min|aug|[mM°0-9])*\(?[\d\/]*\)?(?:[CDEFGAB](?:b|bb)*(?:\#{1,2}|dim|sus|maj|min|aug|[mM°0-9])*[\d\/]*)*\)*(?:\b(?<=\w)|\B(?<!\w))/';
echo preg_replace($regex, '<span class="_c">$1</span>', $lyrics)

请参阅regex demo

原因是您的匹配可以以非单词字符开头或结尾,而\b 单词边界的行为会根据其上下文而有所不同。

在这里,我建议使用类型 2 的自适应动态词边界:

  • (?:\b(?=\w)|\B(?!\w)) - 左侧边界,如果下一个字符是单词 char (\b(?=\w)),则确保当前位置位于单词边界,如果下一个字符不是单词,则确保当前位置位于非单词边界位置字符
  • (?:\b(?&lt;=\w)|\B(?&lt;!\w)) - 右侧边界,如果前一个 char 是 word char,则确保当前位置位于 word 边界,如果前一个 char 不是 word char,则确保当前位置位于非词边界位置。

您也可以观看this YT video of mine,了解更多关于自适应动态词边界的解释和 Python 演示。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-17
    • 1970-01-01
    • 2011-03-20
    • 2012-07-08
    • 2010-10-23
    相关资源
    最近更新 更多