输出导致与正则表达式不匹配的第一个字符

Posted

技术标签:

【中文标题】输出导致与正则表达式不匹配的第一个字符【英文标题】:Output the first character that causes mismatch with a regular expression 【发布时间】:2012-07-21 19:30:49 【问题描述】:

是否可以从导致与正则表达式不匹配的字符串(其索引)中输出第一个字符?是否可以仅使用正则表达式匹配操作或必须使用更复杂的操作?

例如,在 javascript 中,我可能有一个正则表达式 /^\d3\s\d2$/,它匹配包含 3 个数字、后跟一个空格和另外 2 个数字的字符串。我有一个字符串"123a45" 应用这个正则表达式。这样做(例如,"123a45".match(/^\d3\s\d2$/))会返回null,因为正则表达式不匹配。如何获取导致这种不匹配的第一个字符(在本例中为 "a",索引为 3 的字符)?

对此的一个用例可能是根据用于验证的某些正则表达式将用户直接指向导致用户输入的字符串无效的字符。

【问题讨论】:

广义问题很可能是不可行的(一个例子是带有 OR | 的正则表达式,你不知道哪个字符实际上导致了问题,因为有两种可能的情况)。对于一些具体的问题,在某种程度上是可能的。 您能否确定匹配失败时使用了带有| 的正则表达式的哪一部分? 例如:([A-Z][0-9]2|[0-9]2[A-Z]),输入090,你会举报哪个字符?第一个0 还是最后一个0?并且匹配失败是因为它在OR 指定的所有情况下都失败了,正如所指出的那样,原因可能会有所不同。 是的,导致不匹配的第一个字符的简单识别在这种模棱两可的情况下不起作用。 【参考方案1】:

您需要将正则表达式模式分解为部分匹配的所有可能匹配模式,以及从最长匹配到最短匹配(或无匹配)排序的此类模式列表。一旦你得到匹配,计算(部分)匹配的长度,你就会得到导致不匹配的字符的位置。来自该位置且长度为一个字符的子字符串正是该不匹配背后的字符(如果有的话)。如果没有不匹配,则返回空(子)字符串。

var s = "123a45";
alert(s.substr(s.match(/^(\d3\s\d2|\d3\s\d|\d3\s|\d0,3)/)[1].length,1));

http://jsfiddle.net/ETWWS/

【讨论】:

想添加一个简短的解释吗? 您认为这是一个可以应用于各种正则表达式的通用解决方案吗?您认为您可以自动生成包含所有部分匹配的正则表达式的“扩展”正则表达式吗? @jindrichm - 每个固定长度的非替代模式都可以分解。所以下面的例子不能:(1)\d2,4:\d1,2,(2)(\w3\d2|\d3\w2) 是的,我看到大多数正则表达式都不能这样处理。我认为按照@nhahtdh 的建议可能会更好——编写一个自定义解析器。 @jindrichm - 是的,解析器是更安全的解决方案。我发布了我的正则表达式解决方案,因为您要求使用正则表达式,所以......但我必须纠正自己 - 替代模式可能会被打破,所以问题是可变长度(子)模式,所以使用 m,n 或 @987654326 @ 或 *? 是你需要避免的,如果你想使用正则表达式。因此,例如电话号码\d3[-.]\d3[-.]\d4 的正则表达式是可以的,即使有替代分隔符破折号或句点/点。好吧,你必须决定......祝你好运! (Vela štestí a všecho dobré,Jindřichu!)【参考方案2】:

要详细解释输入无效的原因,最好编写一个小型解析器并提供反馈。可以将用户指向导致问题的角色,并提供更有帮助和针对性的错误消息。

在解析器中,您可以使用正则表达式来断言字符串中的某些属性以生成有针对性的错误消息。例如,如果输入必须包含 6 个字符,并且前 3 个字符是数字,后 3 个字符是字母字符,那么您可以编写一个正则表达式来断言输入的长度,以便向用户报告错误。

要么这样,要么只使用您一直在使用的正则表达式并提供一般错误消息(以及有关如何正确输入的有用说明)。一个普通用户最多2-3次就可以正确输入数据。以上,可能是恶意用户,或者输入的数据不适用于所有用户,或者你的指令缺失。

【讨论】:

以上是关于输出导致与正则表达式不匹配的第一个字符的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式不分大小写匹配指定字符串

Java将字符串与正则表达式进行比较-while循环

实用正则表达式匹配和替换

SUBLIME 正则表达式,如何匹配每行出现的第一个汉字

正则表达式删除与第二个字符串匹配的行?

正则表达式如何匹配可选字符