6

これは、例を使用してよりよく説明されています。私はこのような分割を達成したい:

two-separate-tokens-this--is--just--one--token-another

->

["two", "separate", "tokens", "this--is--just--one--token", "another"]

私は素朴に試してみstr.split(/-(?!-)/)ましたが、二重区切り記号の最初の出現には一致しませんが、2番目には一致します(区切り記号が続いていないため):

["two", "separate", "tokens", "this-", "is-", "just-", "one-", "token", "another"]

文字列をループするよりも良い方法はありますか?

ところで、次のステップでは、2 つの連続した区切り記号を 1 つだけに置き換える必要があるため、区切り記号を繰り返してエスケープするようなものです...したがって、最終的な結果は次のようになります。

["two", "separate", "tokens", "this-is-just-one-token", "another"]

それがたった1ステップで達成できたら、それは本当に素晴らしいことです!

4

6 に答える 6

8

str.match(/(?!-)(.*?[^\-])(?=(?:-(?!-)|$))/g);

このフィドルを確認してください。


説明:

非貪欲なパターン(?!-)(.*?[^\-])は、最初も最後もダッシュ文字ではない文字列に一致し、パターンで(?=(?:-(?!-)|$))は、そのような一致の後に単一のダッシュ文字または行末が続く必要があります。修飾子は、単一の (最初の) 出現だけでなく、すべての出現を検索するように/g関数を強制します。match


編集 (OPのコメントに基づく):

str.match(/(?:[^\-]|--)+/g);

このフィドルを確認してください。

説明:

パターン(?:[^\-]|--)は、ダッシュ以外の文字または二重ダッシュの文字列に一致します。Sign+は、前のパターンからのこのような一致は、できるだけ多く乗算する必要があると述べています。修飾子は、単一の (最初の) 出現だけでなく、すべての出現を検索するように/g関数を強制します。match

ノート:

パターン /(?:[^-]|--)+/g は Javascript でも機能しますが、JSLint では-角括弧内でエスケープする必要があります。そうしないと、エラーが発生します。

于 2012-08-13T18:13:36.567 に答える
2

否定的な後読みアサーションと否定的な先読みが必要になります。

(?<!-)-(?!-)

http://regexr.com?31qrn

残念ながら、javascript 正規表現パーサーは否定的な後読みをサポートしていません。唯一の回避策は、後で結果を調べて、後読みアサーションに失敗した可能性のある一致を削除することです (または、この場合はそれらを単一の一致に結合します)。

于 2012-08-13T18:08:14.847 に答える
2

@Ωmega は のmatch代わりにを使用するという正しい考えを持っていますsplitが、彼の正規表現は必要以上に複雑です。これを試してください:

s.match(/[^-]+(?:--[^-]+)*/g);

それはあなたが期待する通りに動作します: 1 つ以上の非ハイフンを消費し、二重ハイフンに遭遇した場合はそれを消費し、非ハイフンを消費し続けます。必要に応じて繰り返します。


編集:どうやらソース文字列には、区切り文字として扱われるべきではない、 2つ以上の連続したハイフンの実行が含まれている可能性があります。+これは、2 番目のハイフンにa を追加することで処理できます。

s.match(/[^-]+(?:--+[^-]+)*/g);

{min,max}数量詞を使用することもできます。

s.match(/[^-]+(?:-{2,}[^-]+)*/g);
于 2012-08-13T19:05:16.510 に答える
0

そのような否定的な後読みなしでこれを達成できます(@jbabeyが言及したように、これらはJSではサポートされていません)(この記事に触発されました):

\b-\b
于 2012-08-13T18:16:58.817 に答える
0

JSの正規表現エンジンだけでそれを行う方法がわかりません。手動で解析するよりも少し複雑なこの方法でそれを行うことができます:

var str = "two-separate-tokens-this--is--just--one--token-another";
str = str.replace(/--/g, "#!!#");
var split = str.split(/-/);
for (var i = 0; i < split.length; i++) {
    split[i] = split[i].replace(/#!!#/g, "--");
}

実際のデモ: http://jsfiddle.net/jfriend00/hAhAB/

于 2012-08-13T18:12:06.563 に答える
0

'----'.replace('--', '-')正規表現がエッジ ケース (5 つの連続する区切り記号など) ではあまり良くなく、二重の区切り記号を単一の区切り記号に置き換える必要があったことを考えると (そして、では'---'なくGive であるため、これもまた難しくなります'--') 関数を作成しました。文字をループし、すべてを一度に実行します(ただし、文字列アキュムレータの使用が遅くなる可能性があることを懸念しています:-s)

f = function(id, delim) {
    var result = [];
    var acc = '';
    var i = 0;
    while(i < id.length) {
        if (id[i] == delim) {
            if (id[i+1] == delim) {
                acc += delim;
                i++;
            } else {
                result.push(acc);
                acc = '';
            }
        } else {
            acc += id[i];
        }
        i++;
    }

    if (acc != '') {
        result.push(acc);
    }

    return result;
    }

そしていくつかのテスト:

> f('a-b--', '-')
["a", "b-"]
> f('a-b---', '-')
["a", "b-"]
> f('a-b---c', '-')
["a", "b-", "c"]
> f('a-b----c', '-')
["a", "b--c"]
> f('a-b----c-', '-')
["a", "b--c"]
> f('a-b----c-d', '-')
["a", "b--c", "d"]
> f('a-b-----c-d', '-')
["a", "b--", "c", "d"]

(最後のトークンが空の場合、スキップされることを意味します)

于 2012-08-14T08:57:58.723 に答える