NSRegularExpression与数字符号不匹配(#)

时间:2017-08-17 15:25:52

标签: ios regex swift unicode nsregularexpression

我正在使用Guitar Chord转换器,因此从给定的文本文件中,我想识别吉他和弦。例如G#,Ab,F#m等

我几乎就到了!由于数字符号(哈希标记),我已经遇到了一些问题。

例如,您不能在正则表达式模式中包含数字符号。 NSRegularExpression不会使用以下内容进行初始化:

let fail:    String = "\\b[ABCDEFG](b|#)?\\b"
let success: String = "\\b[CDEFGAB](b|\\u0023)?\\b"

我必须专门提供unicode角色。我可以忍受。

但是,现在我有了一个NSRegularExpression对象,当我有一行文本时,它不会匹配这些(sharps =数字符号),如:

Am Bb G#C Dm F E

当它开始处理G#时,与第二个捕获组关联的锐利不匹配。 (即NSTextCheckingResult的第二个范围有一个NSNotFound的位置)注意,它适用于Bb ...它匹配' b'

我想知道我需要在这做什么。看来文档并没有涵盖这种情况。#'#'实际上有时在正则表达式模式中使用(我认为与评论或某事物相关)

一件很棒的事情就是不必查找#的unicode标识符,而只是将其用作String"#"然后转换它,以便它与模式很好地匹配。事实上,\ u0023实际上不是与#...

相关联的代码

2 个答案:

答案 0 :(得分:2)

\b word boundary是一个依赖于上下文的构造。它在4个上下文中匹配:1)在字符串开头和单词字符之间,2)在单词char和字符串结尾之间,3)在单词和非单词之间,4)在非单词和单词char之间。 / p>

你的正则表达式是这样编写的,最终正则表达式引擎在\b之后看到#,这意味着只有#后面有一个单词char才会匹配。

如果您将\b替换为(?!\w),如果当前位置右侧有一个字词char,则会出现匹配失败的否定前瞻,它会起作用。

所以,你可以使用

\\b[CDEFGAB](b|\\u0023)?(?!\\w)

请参阅regex demo

<强>详情

  • \b - 字边界
  • [CDEFGAB] - 来自集合
  • 的字符
  • (b|\\u0023)? - b#
  • 的可选序列
  • (?!\\w) - 一个负面预测未通过匹配(并导致回溯到前面的模式!为避免这种情况,请在+之后添加?以防止回溯到该模式中)如果有紧靠当前位置右侧的单词char。

答案 1 :(得分:0)

(我想首先说@WiktorStribiżew是一个巨大的帮助,如果没有他我现在写的东西是不可能的!我不关心StackOverflow积分和代表,所以如果你喜欢这个答案,请提出他的回答。)

这个问题花了很多次,并且有一些问题在继续。 最终应该调用此问题 如何在iOS上使用Regex检测文本文件中的音乐和弦?

答案是(到目前为止),而不仅仅是。

音乐理论中的崩溃课程

在音乐中你有音符。它们由A->G和可选符号{strong>意外之间的字母组成。 (注意事项涉及播放该音符时听到的声音的声频)意外可以是平面(表示为或仅仅b) ,或清晰(表示为或简称#,因为这些更容易在键盘上输入)。意外的作用是使音符成为半音高(#)或低音(b)。因此,F#与Gb具有相同的声频。在钢琴上,白键是没有意外的音符,黑键表示偶然的音符。根据音乐片段的某些因素,该片段不会混合意外类型。它将是整个作品或锐利的平面。 (取决于乐曲的音乐键,但这与此不相关。)

就正则表达而言,你有类似ABCDEFG的东西吗?确定笔记。实际上它更复杂。

然后,音乐和弦由根音符组成,它是和弦类型。有超过50种和弦。他们有一个独特的“文本签名”。此外,“主要”和弦有空签名。所以在伪正则表达方面你有一个和弦:

[ABCDEFG](b|#)?(...|...|...)?

其中您识别为音符的第一部分(如前所述),最后一个可选项是确定和弦类型。省略了不同的类型,但可以像m(对于小和弦)或maj7#5一样简单(对于具有增强的第5和弦的主要第7和弦...不要担心它。只知道有很多字符串常量来表示和弦类型)

然后最后,使用吉他,你经常会有相应的低音音符,它会稍微改变和弦的音调。你通过添加斜杠然后注释来表示这一点,给出一般的假形:

[ABCDEFG](b|#)?(...|...|...)?(/[ABCDEFG](b|#)?)? // NOT real Regex
real examples: C/F or C#m/G# and so on

其中最后一部分有一个斜杠,然后是相同的模式来识别一个音符。

所以把这些放在一起,一般来说我们想要找到可以采用多种形式的和弦,例如:

F Gm C#maj7/G# F/C Am A7 A7/F# Bmaj13#11

我希望找到一个正则表达式来统治它们。我最终编写了有效的代码,虽然看起来我有点被黑了以获得我想要的结果。

你可以用Swift写的see this code here。它并不完整,但我会解析一个字符串,返回原始字符串中的和弦结果列表及其文本范围。从那里你必须完成实施以满足你的需求。

iOS上存在一些问题:

  • iOS根本无法处理数字符号(#)。当提供正则表达式模式或匹配文本时,我要么必须用它的unicode \ u0023替换#,或者最终工作的是用另一个字符(例如'S')替换所有出现的#,然后在regex做之后将其转换回来这是事情。因此,我编写的这段代码经常在做任何事情之前对模式或输入文本进行“消毒”。

  • 我无法使用Regex模式来完美地解析和弦结构。对于带有低音音符的Chord来说它并不完全有效,但它会成功地将Chord与低音音符相匹配,然后我必须将这两个组件分开并分别解析它们,然后重新组合它们

  • 正则表达式实际上是一种伏都教,我认为对于许多人如此困惑的事情而言,它也很糟糕,它也有不同的平台相关实现。例如,Wiktor向我推荐了他编写的正则表达式模式,以帮助我解决www.regex101.com上的问题,这将在该网站上工作,但这些在iOS上无效,NSRegularExpression会引发错误(通常它有一些东西)与#字符有关)

  • 我的解决方案完全不考虑性能。它只是想让它发挥作用。