【问题标题】:IBAN Regex design [duplicate]IBAN 正则表达式设计 [重复]
【发布时间】:2017-11-23 04:29:14
【问题描述】:

请帮助我设计将所有 IBAN 与所有可能的空格匹配的正则表达式。因为我找到了那个,但它不适用于空格。

[a-zA-Z]{2}[0-9]{2}[a-zA-Z0-9]{4}[0-9]{7}([a-zA-Z0-9]?){0,16}

我至少需要那种格式:

DE89 3704 0044 0532 0130 00
AT61 1904 3002 3457 3201
FR14 2004 1010 0505 0001 3

【问题讨论】:

  • 您是否尝试在所需位置插入 零或一个空格?不要害怕,修改后的正则表达式只要稍微摆弄一下就不会爆炸。
  • FWIW,不能可靠地验证 iban。要做到这一点,还有很多工作要做。
  • this one from Apache Commons 是一个很好的、广泛的可用列表。您可以收集所有已定义的模式并调整它们以接受空白。例如:DE\d{2}\s*\d{4}\s*\d{4}\s*\d{4}\s*\d{4}\s*\d{2} 将匹配您的第一个示例。
  • 要使用所有可能的空格验证 IBAN,只需在验证之前删除空格,这会使事情变得相当简单。但实际上你不能完全通过正则表达式进行验证,因为验证的主要关键是校验和。
  • 因此,要验证 iban,我会:1) 规范化:转换为大写并删除除 [A-Z0-9] 之外的任何内容 2) 匹配模式 [A-Z]{2}[0-9]{2}[A-Z0-9]{1,30} 3) 验证校验和。此外,您可以检查(特定于国家/地区的)长度,但在大多数用例中不需要这样做,除非您想通过重新计算校验和来排除有人编造了 IBAN。

标签: regex iban


【解决方案1】:

仅以来自这些国家/地区的 IBAN 为例:
以 2 个字母开头,然后是 2 个数字。
然后在每 4 位数字前留出一个空格,可选择以 1 位或 2 位数字结尾:

\b[A-Z]{2}[0-9]{2}(?:[ ]?[0-9]{4}){4}(?!(?:[ ]?[0-9]){3})(?:[ ]?[0-9]{1,2})?\b    

regex101 test here

请注意,如果目的是验证完整的字符串,则可以简化正则表达式。
由于那时不需要负前瞻(?!...)
而单词边界\b可以替换为行的开头^和结尾$

^[A-Z]{2}[0-9]{2}(?:[ ]?[0-9]{4}){4}(?:[ ]?[0-9]{1,2})?$

此外,如果有 4 组 4 个连接的数字无关紧要,则可以进一步简化。

^[A-Z]{2}(?:[ ]?[0-9]){18,20}$

备注

但是,如果您想匹配来自世界各地的 IBAN 号码?
那么IBAN的BBAN部分最多可以有30个数字或大写字母。 Reference
并且可以用空格或破折号或两者之间的任何一种书写。
例如:CC12 XXXX 12XX 1234 1234 1234 1234 1234 123

因此,匹配带有长 IBAN 的字符串的正则表达式会变得更长一些。

^([A-Z]{2}[ \-]?[0-9]{2})(?=(?:[ \-]?[A-Z0-9]){9,30}$)((?:[ \-]?[A-Z0-9]{3,5}){2,7})([ \-]?[A-Z0-9]{1,3})?$

regex101 test here

另请注意,纯正则表达式解决方案无法进行计算。
因此,要实际验证 IBAN 号码,则需要额外的代码。

示例 Javascript 代码段:

function smellsLikeIban(str){
 return /^([A-Z]{2}[ \-]?[0-9]{2})(?=(?:[ \-]?[A-Z0-9]){9,30}$)((?:[ \-]?[A-Z0-9]{3,5}){2,7})([ \-]?[A-Z0-9]{1,3})?$/.test(str);
}

function validateIbanChecksum(iban) {       
  const ibanStripped = iban.replace(/[^A-Z0-9]+/gi,'') //keep numbers and letters only
                           .toUpperCase(); //calculation expects upper-case
  const m = ibanStripped.match(/^([A-Z]{2})([0-9]{2})([A-Z0-9]{9,30})$/);
  if(!m) return false;
  
  const numbericed = (m[3] + m[1] + m[2]).replace(/[A-Z]/g,function(ch){
                        //replace upper-case characters by numbers 10 to 35
                        return (ch.charCodeAt(0)-55); 
                    });
  //The resulting number would be to long for javascript to handle without loosing precision.
  //So the trick is to chop the string up in smaller parts.
  const mod97 = numbericed.match(/\d{1,7}/g)
                          .reduce(function(total, curr){ return Number(total + curr)%97},'');

  return (mod97 === 1);
};

var arr = [
 'DE89 3704 0044 0532 0130 00', // ok
 'AT61 1904 3002 3457 3201', // ok
 'FR14 2004 1010 0505 0001 3', // wrong checksum
 'GB82-WEST-1234-5698-7654-32', // ok
 'NL20INGB0001234567', // ok
 'XX00 1234 5678 9012 3456 7890 1234 5678 90', // smells ok
 'YY00123456789012345678901234567890', // smells ok
 'NL20-ING-B0-00-12-34-567', // wrong format, but valid checksum
 'XX22YYY1234567890123', // wrong checksum
 'foo@i.ban' // Not even smells like IBAN
];
arr.forEach(function (str) {
  console.log('['+ str +'] Smells Like IBAN:    '+ smellsLikeIban(str));
  console.log('['+ str +'] Valid IBAN Checksum: '+ validateIbanChecksum(str))
});

【讨论】:

  • 您在哪里看到正则表达式中的 4 字符银行代码?例如 NL20INGB0001234567 和 GB82WEST12345698765432。
  • @wind-rider 编写正则表达式以适应问题所要求的格式。其中一些数字按 4 分组。但实际上,IBAN 的 BBAN 部分最多可以包含 30 个特定于国家/地区的字母数字字符。
  • @wind-rider 为了完整起见,我已经包含了其他 IBAN 的正则表达式。
  • @wind-rider 在检查了维基百科并针对来自不同国家的布局进行了测试后,我不得不稍微更改一下正则表达式。并包含一个 regex101 测试。
  • @Vituel 确保 BBAN 部分不包含超过 30 个字母或数字。参见 IBAN 的定义。如果只是依赖于其他组,那么 (5*6)+3 的 BBAN 仍然可以通过。正则表达式不仅涉及模式允许的内容,还涉及它不允许的内容。
【解决方案2】:

以下建议可能适用于您提供的模式:

[A-Z]{2}\d{2} ?\d{4} ?\d{4} ?\d{4} ?\d{4} ?[\d]{0,2}

Try it on regex101


说明

  • [A-Z]{2}\d{2} ? 2 个大写字母后跟 2 个数字(可选空格)
  • \d{4} ? 4 位,重复 4 次(可选空格)
  • [\d]{0,2} 0 到 2 位数字

【讨论】:

  • 这将不允许开头后的字母。他现有的模式允许这样做。
【解决方案3】:

您可以像这样使用正则表达式:

^[A-Z]{2}\d{2} (?:\d{4} ){3}\d{4}(?: \d\d?)?$

Working demo

这将只匹配那些字符串格式

【讨论】:

  • 谢谢,但如果您删除空格,这将不起作用。我的意思是我不明白如何处理任何空格位置(包括没有空格)。
  • @Maximus,正则表达式可以帮助您匹配模式,如果您需要匹配任意字符,那么您将不得不一直使用空格检查,例如:[A-Z]\s*[A-Z]\s*\d\s*\d\s*.....etc。您的问题不清楚,您应该更新它并使用更多示例添加更多描述。但是,如果我的回答回答了您的问题并且您只想将空格设为可选,则只需将 ? 附加到每个空格
【解决方案4】:

最好查找正确的 IBAN 号码的规范。但是,如果您想要一个类似于您现有的正则表达式,但带有空格,您可以使用以下一个:

^[a-zA-Z]{2}[0-9]{2}\s?[a-zA-Z0-9]{4}\s?[0-9]{4}\s?[0-9]{3}([a-zA-Z0-9]\s?[a-zA-Z0-9]{0,4}\s?[a-zA-Z0-9]{0,4}\s?[a-zA-Z0-9]{0,4}\s?[a-zA-Z0-9]{0,3})?$

这是一个活生生的例子:https://regex101.com/r/ZyIPLD/1

【讨论】:

    猜你喜欢
    • 2019-08-08
    • 2017-04-11
    • 2014-06-17
    • 2021-04-26
    • 2019-08-30
    • 2021-10-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多