如何在ColdFusion(或Java)中实现这个正则表达式?

4

我在regexlib.com找到了这个非常有用的正则表达式,但我不知道如何在我的应用程序中实现它。

(?:(?:(?<Feet>\d+)[ ]*(?:'|ft)){0,1}[ ]*(?<Inches>\d*(?![/\w])){0,1}(?:[ ,\-]){0,1}(?<Fraction>(?<FracNum>\d*)\/(?<FracDem>\d*)){0,1}(?<Decimal>\.\d*){0,1}(?:\x22| in))|(?:(?<Feet>\d+)[ ]*(?:'|ft)[ ]*){1}

我使用他们的在线测试工具进行了测试,它确实可以满足我所有需求。将其作为 ColdFusion 的 REFind() 参数粘贴并没有按预期工作,并返回一个无用的错误消息。

我正在使用 ColdFusion,因此如果需要,我可以访问 Java 类。Java 或 ColdFusion 的答案都很有帮助。

一个好的示例字符串可能是:5' 1/2"

编辑

我需要利用正则表达式中的组来提取数据,而不仅仅是用它来验证字符串。我想这意味着我应该使用 REMatch()?请原谅我的正则表达式经验不足!

编辑 2

使用此表达式与 REFind() 似乎不起作用:

(?:(?:(\\d+)[ ]*(?:'|ft)){0,1}[ ]*(\\d*(?![/\\w])){0,1}(?:[ ,\\-]){0,1}((\\d*)\\/(\\d*)){0,1}(\\.\\d*){0,1}(?:\\x22| in))|(?:(\\d+)[ ]*(?:'|ft)[ ]*){1}

它无法找到大部分测试数据的匹配项,包括使用regexlib.com测试器返回匹配项的数据:1ft 2-3/4 in, 2' 3 4/5", 3ft, 4', 5 in, 6", 7.125 in, 3ft 4.5 in


关于编辑2,它是作为一个确切的字符串传递而不是作为Java代码传递的吗?如果是这样,请尝试将双斜杠更改为单斜杠。 - lins314159
它作为字符串传递,单独处理斜杠似乎起到了作用,还进行了一些检查以确保subs.pos数组的每个结果都不包含0(这会导致错误)。谢谢! - Jordan Sitkin
3个回答

4

ColdFusion不支持?<foo>语法。我不熟悉该语法,但它似乎被用于给捕获的子表达式分配名称。例如,第一个子表达式是表示英尺的数字,因此它有?<Feet>标签。您可以删除这些标签而不影响正则表达式匹配。

我没有测试过,但我在那个正则表达式中看到的所有其他元素都受ColdFusion支持,因此在删除所有?<foo>标签后,REFind()应该能够工作。当然,使用“returnsubexpressions”参数可以访问子表达式。请参阅标准CF文档上的REFind()。

顺便说一下,正则表达式似乎有点冗长。{0,1}很少见,因为?意味着相同的事情。{1}甚至更少见,因为它是分组的默认值,因此可以完全省略。

补充说明

regex = "(?:(?:(\\d+)[ ]*(?:'|ft)){0,1}[ ]*(\\d*(?![/\\w])){0,1}(?:[ ,\\-]){0,1}((\\d*)\\/(\\d*)){0,1}(\\.\\d*){0,1}(?:\\x22| in))|(?:(\\d+)[ ]*(?:'|ft)[ ]*){1}";
subs = REFind(regex,input,1,"True");
if (subs.pos[1] eq 0) {
  found = "False";
} else {
  found = "True";
  feet = Mid(input,subs.pos[2],subs.len[2]);
  inches = Mid(input,subs.pos[3],subs.len[3]);
  fraction = Mid(input,subs.pos[4],subs.len[4]);
  fracNum = Mid(input,subs.pos[5],subs.len[5]);
  fracDem = Mid(input,subs.pos[6],subs.len[6]);
  decimal = Mid(input,subs.pos[7],subs.len[7]);
  if (feet is "") {
    // Use the _other_ feet
    feet = Mid(input,subs.pos[8],subs.len[8]);
  }
}

谢谢,确实可以在没有那些标签的情况下工作,正如@lins314159所指出的。您知道我如何使用不同的语法访问这些组吗? - Jordan Sitkin
哇,谢谢!不过,根据我上面的示例输入,发现返回值为false:5' 1/2"。使用regexlib.com上的测试器可以得到一组匹配结果。 - Jordan Sitkin
据我所知,?<foo> 结构是微软的扩展,不被 C#、VB 等之外的任何语言支持。虽然我不太确定如何用谷歌搜索 ?<foo> 进行验证。 :-) - Ben Doom

1

看起来你使用的表达式是C#语法,它支持命名组(例如(?<Decimal>\.\d*))。Java不支持命名组,并将其视为完全不同的内容。由于这些命名组并没有被使用,所以只需要删除命名部分即可(例如(?<Decimal>\.\\d*)变成了(\.\\d*))。

Pattern.compile("(?:(?:(\\d+)[ ]*(?:'|ft)){0,1}[ ]*(\\d*(?![/\\w])){0,1}(?:[ ,\\-]){0,1}((\\d*)\\/(\\d*)){0,1}(\\.\\d*){0,1}(?:\\x22| in))|(?:(\\d+)[ ]*(?:'|ft)[ ]*){1}");

我在最初的问题中应该更清楚:我确实需要利用组来提取匹配的值。您知道我如何在Java语法中实现这一点吗? - Jordan Sitkin
你需要获取组号(从1开始)。要获取Inches组,你可以使用matcher.group(2) - lins314159

0

Java的字符串对象支持正则表达式。String.match()、String.replaceAll()和String.replaceFirst()。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接