这是一个RegEx问题。
感谢您的帮助,请耐心等待,因为RegEx绝对不是我的力量!
完全作为背景......我的理由是我想使用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> ]
使用此正则表达式时出现问题:
以下是传入字符串的更完整定义:
以下是我一直在使用的测试代码:
<!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>
答案 0 :(得分:3)
^([a-z]+)(?:(-?\d*.?\d+)[^\d\n\r.-]*(-?\d*.?\d+)?)?
解释
^ # start of string ([a-z]+) # any number of characters, match into group 1 (?: # non-capturing group (-?\d*.?\d+) # first number (optional singn & decimal point, digits) [^\d\n\r.-]* # delimiting characters (anything but these) (-?\d*.?\d+)? # second number )? # end non-capturing group, make optional
使用“不区分大小写”标记。
答案 1 :(得分:2)
你的“模式”由一个或多个字母组成,后跟一个十进制数字,后跟另一个用逗号或空格分隔的字母。
正则表达式:/([a-z]+)(-?(?:\d*\.)?\d+)(?:[,\s]+|(?=-))(-?(?:\d*\.)?\d+)/i
答案 2 :(得分:2)
我必须执行非常类似的数据解析,以便在全国最大的赛道会议上报告实时结果。 http://ksathletics.com/2013/statetf/liveresults.js虽然涉及很多客户端和服务器端代码,但原则是相同的。事实上,这类数据实际上是相同的。
我建议您不要使用一个“jumbo”正则表达式,而是使用一个表达式来分隔数据块,另一个表达式将每个数据块分成其主标识符和以下值。这通过允许第二级正则表达式匹配数据值的定义而不是必须区分分隔符来解决各种分隔符的问题。 (这也比将所有逻辑放入单个正则表达式更有效。)
这是一个经过测试的解决方案,可用于您提供的输入。
<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
更新:结果与您想要的指定输出完全相同。然而,人们想到的一个想法是,您是否也想要或需要从字符串到数字的类型转换。你也需要那个吗?我只想到解析数据之后的下一步。
答案 3 :(得分: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" ] ]
答案 4 :(得分:1)
您可以尝试使用此模式:
/([a-z]+)(-?(?:\d*\.)?\d+)?(?:\s+|,|(-(?:\d*\.)?\d+))?(-?(?:\d*\.)?\d+)?/
(有点长,但似乎有效)
请注意,最后一个数字可以位于捕获组\ 3或\ 4
中