2

これは正規表現に関する質問です。

助けてくれてありがとう。正規表現は間違いなく私の強みではないので、しばらくお待ちください!

完全に背景として...質問する理由は、RegExを使用してSVGパスデータセグメントに似た文字列を解析したいからです。セグメントとそのセグメント属性の両方を解析する以前の回答を探しましたが、後者を適切に処理するものは見つかりませんでした。

解析する必要がある文字列の例を次に示します。

M-11.11,-22
L.33-44  
ac55         66 
h77  
M88 .99  
Z 

次のように、文字列を配列に解析する必要があります。

["M", -11.11, -22]
["L", .33, -44]
["ac", 55, 66]
["h", 77]
["M", 88, .99]
["Z"]

これまでのところ、この回答でこのコードを見つけました: Parsing SVG "path" elements with C# - are there libraries out there to do this? 投稿はC#ですが、正規表現はjavascriptで役立ちました:

var argsRX = /[\s,]|(?=-)/; 
var args = segment.split(argsRX);

これが私が得るものです:

 [ "M", -11.11, -22, <empty element>  ]
 [ "L.33", -44, <empty>, <empty> ]
 [ "ac55", <empty>, <empty>, <empty>, 66 <empty>  ]
 [ "h77", <empty>, <empty>  
 [ "M88", .99, <empty>, <empty> ]
 [ "Z", <empty> ]

この正規表現を使用する際の問題:

  • 不要な空の配列要素が、各文字列の配列の最後に配置されています。
  • 複数のスペースが区切り文字である場合、余分なスペースごとに不要な空の配列要素が作成されます。
  • 開始文字の直後に数字が続く場合、その数字は文字に付加されますが、別の配列要素になる必要があります。

着信文字列のより完全な定義を次に示します。

  • 各文字列は 1 つ以上の文字 (大文字と小文字が混在) で始まります。
  • 次はゼロ以上の数字です。
  • 数値にはマイナス記号が含まれる場合があります (常に先行します)。
  • 数値には、数値のどこかに小数点がある場合があります (末尾を除く)。
  • 可能な区切り文字は、コンマ、スペース、スペース、マイナス記号です。
  • 前後にスペースを含むコンマも区切り文字として使用できます。
  • マイナス記号はデリミタですが、番号と共に残す必要があります。
  • 開始文字の直後に数字が続く場合があり (スペースなし)、その数字は分離する必要があります。

これが私が使用しているテストコードです:

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; }
</style>

<script>
    $(function(){


var pathData = "M-11.11,-22 L.33-44  ac55    66 h77  M88 .99  Z" 

// separate pathData into segments
var segmentRX = /[a-z]+[^a-z]*/ig;
var segments = pathData.match(segmentRX);

for(var i=0;i<segments.length;i++){
    var segment=segments[i];
    //console.log(segment);

    var argsRX = /[\s,]|(?=-)/; 
    var args = segment.split(argsRX);
    for(var j=0;j<args.length;j++){
        var arg=args[j];
        console.log(arg.length+": "+arg);
    }

}

    }); // end $(function(){});
</script>

</head>

<body>
</body>
</html>
4

5 に答える 5

3
^([az]+)(?:(-?\d*.?\d+)[^\d\n\r.-]*(-?\d*.?\d+)?)?

説明

^ # 文字列の開始
([az]+) # 任意の数の文字、グループ 1 に一致
(?: # 非キャプチャ グループ
  (-?\d*.?\d+) # 最初の数字 (オプションの記号と小数点、数字)
  [^\d\n\r.-]* # 区切り文字 (これら以外)
  (-?\d*.?\d+)? # 2 番目の数字
)? # 非キャプチャ グループを終了し、オプションにします

「大文字と小文字を区別しない」フラグとともに使用します。

于 2013-06-10T06:28:02.000 に答える
2

私は、国内最大の陸上競技会でライブ結果を報告するために、非常によく似たデータ解析を実行する必要がありました。http://ksathletics.com/2013/statetf/liveresults.js クライアント側とサーバー側の両方のコードが多数含まれていましたが、原則は同じです。実際、データの種類は実質的に同じでした。

1 つの「ジャンボ」正規表現を使用するのではなく、データの断片を分離する 1 つの表現と、各データをその主要な識別子とそれに続く値に分割する別の表現を使用することをお勧めします。これにより、区切り文字を区別するのではなく、第 2 レベルの正規表現をデータ値の定義と一致させることで、さまざまな区切り文字の問題が解決されます。(これは、すべてのロジックを単一の正規表現に入れるよりも効率的です。)

これは、あなたが与えた入力で動作するようにテストされたソリューションです。

<script>
var pathData = "M-11.11,-22 L.33-44  ac55    66 h77  M88 .99  Z" 

function parseData(pathData) {
    var pieces = pathData.match(/([a-z]+[-.,\d ]*)/gi), i;
    /* now parse each piece into its own array */
    for (i=0; i<pieces.length; i++)
        pieces[i] = pieces[i].match(/([a-z]+|-?[.\d]*\d)/gi);
    return pieces;
}

pathPieces = parseData(pathData);
document.write(pathPieces.join('<br />'));
console.log(pathPieces);
</script>

http://dropoff.us/private/1370846040-1-test-path-data.html

更新:結果は、必要な指定された出力とまったく同じです。しかし、頭に浮かんだ 1 つの考えは、文字列から数値への型変換も必要かどうかということでした。それも必要ですか?データの解析を超えた次のステップを考えているところです。

于 2013-06-10T06:28:59.553 に答える
2
function parsePathData(pathData)
{
    var tokenizer = /([a-z]+)|([+-]?(?:\d+\.?\d*|\.\d+))/gi,
        match,
        current,
        commands = [];

    tokenizer.lastIndex = 0;
    while (match = tokenizer.exec(pathData))
    {
        if (match[1])
        {
            if (current) commands.push(current);
            current = [ match[1] ];
        }
        else
        {
            if (!current) current = [];
            current.push(match[2]);
        }
    }
    if (current) commands.push(current);
    return commands;
}

var pathData = "M-11.11,-22 L.33-44  ac55    66 h77  M88 .99  Z";
var commands = parsePathData(pathData);
console.log(commands);

出力:

[ [ "M", "-11.11", "-22" ],
  [ "L", ".33", "-44" ],
  [ "ac", "55", "66" ],
  [ "h", "77" ],
  [ "M", "88", ".99" ],
  [ "Z" ] ]
于 2013-06-10T06:31:00.030 に答える
2

「パターン」は、1 つ以上の文字、その後に続く 10 進数、さらにカンマまたは空白で区切られた別の文字で構成されます。

正規表現:/([a-z]+)(-?(?:\d*\.)?\d+)(?:[,\s]+|(?=-))(-?(?:\d*\.)?\d+)/i

于 2013-06-10T06:12:42.053 に答える
1

このパターンで試すことができます:

/([a-z]+)(-?(?:\d*\.)?\d+)?(?:\s+|,|(-(?:\d*\.)?\d+))?(-?(?:\d*\.)?\d+)?/

(少し長いですが、うまくいくようです)

最後の番号は、キャプチャ グループ \3 または \4 に含まれる可能性があることに注意してください。

于 2013-06-10T06:52:50.270 に答える