多个组的正则表达式不起作用 - Java 1.7 到 1.8 - ScriptEngine Rhino to Nasho



我遇到了这个问题中描述的正则表达式问题

字符串如下:<SPAN>06-24-2015 11:28AM 0250 01 90775 05342</SPAN>

1.7 Java上的JS代码工作正常: 正则表达式 :

/<span>(\d{2}-\d{2}-\d{4})\s*?(\d{1,2}:\d{2}\s*?(?:am|pm))\s*?(?:<\/SPAN><BR\/?><SPAN>)?\s*?((\d[ -]*?){13,17})\s*?<\/span>/i

但是在 1.8 Java 中同样不起作用,如顶部共享的问题中所述。 得到这个问题的建议,我逐组创建了我的正则表达式,并知道只有正则表达式的最后一部分在 1.8 中不起作用。

ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
String js = "var fileSrc = '<SPAN>06-24-2015  11:28AM  0250 01 90775 05342</SPAN>';"
+ "var trans_regex = /<span>(\d{2}-\d{2}-\d{4})\s*?(\d{1,2}:\d{2}\s*?(?:am|pm))\s*?(?:<\/SPAN><BR\/?><SPAN>)?\s*?((\d[ -]*?){13,17})\s*?/i;"
+ "print('executed regex result : ' + trans_regex.exec(fileSrc) ) ; ";
Object result = engine.eval(js);

在上面共享的代码中,正则表达式被截断为:

/<span>(\d{2}-\d{2}-\d{4})\s*?(\d{1,2}:\d{2}\s*?(?:am|pm))\s*?(?:<\/SPAN><BR\/?><SPAN>)?\s*?((\d[ -]*?){13,17})\s*?/i

其结果为:

executed regex result : <SPAN>06-24-2015  11:28AM  0250 01 90775,06-24-2015,11:28AM,0250 01 90775,5

实际的正则表达式是:

/<span>(\d{2}-\d{2}-\d{4})\s*?(\d{1,2}:\d{2}\s*?(?:am|pm))\s*?(?:<\/SPAN><BR\/?><SPAN>)?\s*?((\d[ -]*?){13,17})\s*?<\/span>/i

任何人都可以建议应该做些什么才能使实际的正则表达式在 1.8 上再次工作。

实际的JS正则表达式可以在这里找到 https://regex101.com/r/ARqNJ4/1

编辑

在 1.7 中,脚本引擎是 Rhino,在 1.8 中是它的 Nashorn

编辑 2

根据评论中的建议,截断的错误正则表达式如下:

要匹配的字符串<SPAN>0250 01 90775 05342</SPAN>

到目前为止使用的正则表达式:

/<span>\s*?((\d[ -]*?){13,17})\s*?/i

输出(不是必需的):

executed regex result : <SPAN>0250 01 90775,0250 01 90775,5

正则表达式在 1.7 中工作:

/<span>\s*?((\d[ -]*?){13,17})\s*?<\/span>/i

据我所知,您需要做的就是在收盘<\/span\>之前添加[^<]*?。此外,您无需转义最后一个跨度的起始<。所以,这是这个脚本:

ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
String js = "var fileSrc = '<SPAN>06-24-2015  11:28AM  0250 01 90775 05342</SPAN>';"
+ "var trans_regex = /\<span\>(\d{2}-\d{2}-\d{4})\s*?(\d{1,2}:\d{2}\s*?(?:am|pm))\s*?(?:<\/SPAN><BR\/?><SPAN>)?\s*?((\d[ -]*?){13,17})\s*?[^<]*?\<\/span\>/i ;"
+ "print('executed regex result : ' + trans_regex.exec(fileSrc) ) ; "
+ "var t_time = trans_regex.exec(fileSrc)[2];"
+ "var t_cc = trans_regex.exec(fileSrc)[3];"
+ "print(" time " + t_time)";
Object result = engine.eval(js);

屈服于此:

executed regex result : <SPAN>06-24-2015  11:28AM  0250 01 90775 05342</SPAN>,06-24-2015,11:28AM,0250 01 90775,5
time 11:28AM

更新 - 解释和替代方案

这是原始正则表达式的最后一组:((\d[ -]*?){13,17})。这对我来说看起来很棘手,但是,我不知道这背后的意图。它的作用:

  1. 匹配一位数字
  2. 匹配零个或多个空格或连字符
  3. 重复步骤 1 和 2 至少 13 次,最多 17 次。

这真的很棘手,因为零个或多个空格或连字符可以在任何地方匹配。我相信意图是这样的:

考虑字符串0250 01.前导'0'将匹配 1 位数字和 0 个其他字符。'2''5'相同.然后,'0 '将匹配一个数字和一个空格。依此类推,最多 13-17 位数字。

显然,Nashorn发动机无法处理这种结构。如果我添加此打印语句:

+ "print (trans_regex.exec(fileSrc));"

那么我会得到这个结果:

<SPAN>06-24-2015  11:28AM  0250 01 90775 05342</SPAN>,06-24-2015,11:28AM,0250 01 90775,5

这告诉我((\d[ -]*?){13,17})匹配0250 01 90775,只有 11 位数字。所以我的"修复"只是在结束<span>开始时抓住其余角色。

根据这个正则表达式演示,你的逻辑应该匹配。

解决方法 1

你可以使连字符或空格部分变得贪婪。 即删除*后的?

((\d[ -]*){13,17})

我会选择这个。

解决方法 2

您可以指定更多重复项,在本例中为 19 个:

((\d[ -]*?){13,19})

恐怕在这种情况下,您也必须更改下限。

最新更新