0

和音を含む行を一致させようとしていますが、呼び出し元に返されたくないため、文字を消費せずに各一致が空白で囲まれているか、行の最初にあることを確認する必要があります。

例えば

Standard Tuning (Capo on fifth fret)

Time signature: 12/8
Tempo: 1.5 * Quarter note = 68 BPM

Intro: G Em7 G Em7

  G                 Em7
I heard there was a secret chord
     G                   Em7
That David played and it pleased the lord
    C                D              G/B     D
But you don't really care for music, do you? 
        G/B                C          D
Well it goes like this the fourth, the fifth
    Em7                 C
The minor fall and the major lift
    D            B7/D#         Em
The baffled king composing hallelujah

Chorus:

G/A   G/B  C           Em         C             G/B   D/A    G
Hal - le-  lujah, hallelujah, hallelujah, hallelu-u-u-u-jah .... 

「68 BPM」の「B」にも一致することを除いて、ほとんど機能します。コードが正しく一致していることを確認するにはどうすればよいですか? Before の B や SUBSIDE の D や E と一致させたくないのですが?

これは、個別の行ごとに一致させるための私のアルゴリズムです。

function getChordMatches(line) {
    var pattern = /[ABCDEFG](?:#|##|b|bb)?(?:min|m)?(?:maj|add|sus|aug|dim)?[0-9]*(?:\/[ABCDEFG](?:#|##|b|bb)?)?/g;
    var chords = line.match(pattern);
    var positions = [];
    while ((match = pattern.exec(line)) != null) {
        positions.push(match.index);
    }

    return {
        "chords":chords,
        "positions":positions
    };
}

つまり、["A"、"Bm"、"C#"] ではなく ["A"、"Bm"、"C#"] の形式の配列が必要です。

編集

受け入れられた回答を使用して機能させました。先頭の空白に対応するために、いくつかの調整を行う必要がありました。時間を割いてくれてありがとう!

function getChordMatches(line) {
    var pattern = /(?:^|\s)[A-G](?:##?|bb?)?(?:min|m)?(?:maj|add|sus|aug|dim)?[0-9]*(?:\/[A-G](?:##?|bb?)?)?(?!\S)/g;
    var chords = line.match(pattern);
    var chordLength = -1;
    var positions = [];

    while ((match = pattern.exec(line)) != null) {
        positions.push(match.index);
    }

    for (var i = 0; chords && i < chords.length; i++) {
        chordLength = chords[i].length;
        chords[i] = chords[i].trim();
        positions[i] -= chords[i].length - chordLength;
    }

    return {
        "chords":chords,
        "positions":positions
    };
}
4

4 に答える 4

1

入力をすでに行に分割していると思います。そして、関数は行を 1 つずつ処理します。

それらを抽出する前に、行に最初の項目としてコードがあることを確認する必要があります。

if (/^\s*[A-G](?:##?|bb?)?(?:min|m)?(?:maj|add|sus|aug|dim)?[0-9]*(?:\/[A-G](?:##?|bb?)?)?(?!\S)/.test(line)) {
    // Match the chords here
}

^\s*行頭からチェックするために前に追加し、最初の和音の後に(?!\S)空白文字または行末があることを確認するために追加しました。\s

A##(それが有効な和音であると仮定して)現在の正規表現と一致しないため、正規表現にいくつかの小さな変更を加えたことに注意してください。正規表現エンジンは、交互にパターンの順序に従って一致をチェックするため、 で#最初に試行され#|##ます。一致するものを見つけ、A#をチェックせずに一致を返し##ます。順序を逆にする##|#か、貪欲な量指定子を使用##?すると問題が解決します。これは、より長い代替を最初にチェックするためです。


「最初のアイテムが和音の場合、残りは和音である」と確信している場合は、一致する代わりに、スペースで分割できます。

line.split(/\s+/);

アップデート

コードが文の中にあるかどうかに関係なく、パターンに一致させたい場合(現在持っているものでそれができます):

/(?:^|\s)[A-G](?:##?|bb?)?(?:min|m)?(?:maj|add|sus|aug|dim)?[0-9]*(?:\/[A-G](?:##?|bb?)?)?(?!\S)/

この正規表現は、質問にあるコードに配置されます。

コードの前に空白文字があるか、行頭に(?:^|\s). ただし、結果の先頭のスペースを削除する必要があります。

\bの代わりに使用する(?:^|\s)と先頭のスペースの問題を回避できますが、意味は異なります。あなたが入力を十分に理解していない限り、私はそれに反対することをお勧めします。


もう 1 つの方法は、文字列を で分割し、\s+各トークンに対して次の正規表現をテストすることです (^先頭と$末尾の に注意してください)。

 /^[A-G](?:##?|bb?)?(?:min|m)?(?:maj|add|sus|aug|dim)?[0-9]*(?:\/[A-G](?:##?|bb?)?)?$/
于 2013-02-03T13:03:27.237 に答える
0

タイトルの特定の質問に答えるには、先読みを使用してください。

 (?=\s)

REに埋め込まれると、次の文字を消費せずに空白にすることができます。

于 2013-02-03T13:12:09.383 に答える
0

\b開始と終了に(単語境界)を追加するとうまくいきます。A-Gまた、の代わりに 使用することもできますABCDEFG。したがって:

> re = /\b[A-G](?:#|##|b|bb)?(?:min|m)?(?:maj|add|sus|aug|dim)?[0-9]*(?:\/[A-G](?:#|##|b|bb)?)?\b/g
/\b[A-G](?:#|##|b|bb)?(?:min|m)?(?:maj|add|sus|aug|dim)?[0-9]*(?:\/[A-G](?:#|##|b|bb)?)?\b/g

> 'G/A   G/B  C           Em         C             G/B   D/A    G'.match(re)
["G/A", "G/B", "C", "Em", "C", "G/B", "D/A", "G"]

> 'Tempo: 1.5 * Quarter note = 68 BPM'.match(re)
null
于 2013-02-03T13:11:40.687 に答える
0

以下を試してください

function getChordMatches( line ) {
    var match,
        pattern = /(?:^|\s)([A-G](?:##?|bb?)?(?:min|m)?(?:maj|add|sus|aug|dim)?\d*(?:\/[A-G](?:##?|bb?)?)?)(?=$|\s)/g,
        chords = [],
        positions = [];

    while ( match = pattern.exec(line) ) {
        chords.push( match[1] );
        positions.push( match.index );
    }

    return {
        "chords" : chords,
        "positions" : positions
    };
}

コードが行の先頭にあるか、スペースが先行していることを確認するために使用(?:^|\s)し、正の先読み(?=$|\s)を使用して、コードの後に​​スペースが続くか、行の末尾にあることを確認します。コード自体をキャプチャするために括弧が追加され、 によってアクセスされmatch[1]ます。

于 2013-02-03T15:46:49.180 に答える