【问题标题】:Regex for Discover credit card发现信用卡的正则表达式
【发布时间】:2012-11-10 03:21:53
【问题描述】:

我已经阅读了this question,但是对于 Discover 卡,起始数字是 6011, 622126-622925, 644-649, 65 而不仅仅是 6011, 65。 (Source)

对于发现卡,我从那个问题^6(?:011|5[0-9]{2})[0-9]{12}$ 中选择了这个正则表达式

我对其进行了修改以涵盖6011644-649& 65,但对于622126-622925,构建正则表达式很难,因为我的正则表达式技能很差。

到目前为止,我有这个正则表达式 6(?:011|5[0-9]{2}|[4][4-9][0-9]|[2]{2}[1-9])[0-9]{2}$,但它只检查 622[1-9]**

如何修改它以使其仅在 622126-622925 之间接受 622*** 案例?

【问题讨论】:

  • 你能不能只使用普通的 Discover Regex 并在下一行以更易读的方式进行检查?
  • 有什么理由不使用非正则表达式数字比较?
  • @YuriyFaktorovich 抱歉没听明白。你的意思是格式化我上面的问题或分两步解决它?如果是后者,我更喜欢使用单个正则表达式。
  • @djechlin 我可以这样做,但是现在所有信用卡检查都是通过正则表达式进行的,并且由于正则表达式技能不佳而切换到整数比较似乎对我的代码不公平。
  • 我的意思是分两步解决它。如果您创建这个复杂的、几乎不可读的正则表达式,因为您没有在其中使用 cmets,任何更改都将非常浪费时间。您还浪费时间尝试使用 Regex 进行数字比较。基本上你是在用锤子敲打螺丝。

标签: regex


【解决方案1】:

即使这张票是 3 年前的,我也遇到了同样的任务,想分享一个 622126-622925 的正则表达式 :)

^(622[1-9]\\d(?<!10|11|9[3-9])\\d(?<!12[0-5]|92[6-9])\\d{10})$

它使用零宽度负向后查找来排除不期望的数字

【讨论】:

    【解决方案2】:

    这是你的正则表达式(demo)

    ^6(?:011\d{12}|5\d{14}|4[4-9]\d{13}|22(?:1(?:2[6-9]|[3-9]\d)|[2-8]\d{2}|9(?:[01]\d|2[0-5]))\d{10})$
    

    不用说,我不会说这很漂亮或易于维护。我建议将数字解析为整数并使用您的编程语言进行检查。

    您还应该使用Luhn algorithm 来检查信用卡号是否有效,虽然您可以理论上使用正则表达式来做到这一点,但它会比这更糟糕很多倍。


    请允许我一步一步地向您展示我是如何到达这个怪物的。首先,这里是你如何匹配每个范围:

    6011        # matches 6011
    65          # matches 65
    64[4-9]     # matches 644-649
    622(1(2[6-9]|[3-9]\d)|[2-8]\d{2}|9([01]\d|2[0-5]))  
                # matches 622126-622925
    

    现在,您要匹配其余的数字:

    6011\d{12}        # matches 6011 + 12 digits
    65\d{14}          # matches 65 + 14 digits
    64[4-9]\d{13}     # matches 644-649 + 13 digits
    622(1(2[6-9]|[3-9]\d)|[2-8]\d{2}|9([01]\d|2[0-5]))\d{10}
                      # matches 622126-622925 + 10 digits
    

    现在您可以结合所有四个,并添加行锚的开始和结束:

    ^(                  # match start of string and open group
     6011\d{12}|        # matches 6011 + 12 digits
     65\d{14}|          # matches 65 + 14 digits
     64[4-9]\d{13}|     # matches 644-649 + 13 digits
     622(1(2[6-9]|[3-9]\d)|[2-8]\d{2}|9([01]\d|2[0-5]))\d{10}
                        # matches 622126-622925 + 10 digits
    )$                  # close group and match end of string
    

    上面的最终产品是先前正则表达式的略微压缩版本,我还使组不捕获(这就是 ?: 的用途)。

    【讨论】:

    • 天哪!现在我看到它是如何变得复杂并超出了我的理解范围。我只是通过将其解析为整数并将其与622126-622925 的情况进行比较来使其工作。感谢 Nerdlord 向我解释这一点! :D
    • @Ashfame 是的,正则表达式中的范围很快就会变得笨拙。就像我说的,您还应该验证校验位是否正确;那是你真的不应该使用正则表达式的东西。
    • 是的,先生!我有一个用于 Luhn 算法的 jQuery 验证插件。
    • 这张测试卡不适合我,而在其他系统上它可以工作,有什么想法吗? 6011 1111 1111 1117
    • 我修改了这个正则表达式,将 16 位限制增加到 19 位:/^6(?:011\d{12,15}|5\d{14,17}|4[4- 9]\d{13,16}|22(?:1(?:2[6-9]|[3-9]\d)|[2-8]\d{2}|9(?:[ 01]\d|2[0-5]))\d{10,13})$/ 此维基百科页面将范围列为 16 - 19 位数字:en.wikipedia.org/wiki/Payment_card_number 此页面包含 16 位和 19 位数字的发现测试卡: freeformatter.com/credit-card-number-generator-validator.html
    【解决方案3】:

    以下是您的选择:

    1. 破解它并构建一个非常复杂的正则表达式。正则表达式不适合这种整数比较,所以你想出的东西一定很长、不复杂和不可维护。请参阅 Regex for number check below a value 和有关此主题的类似 SO 问题。
    2. 在您的代码中使用整数比较。

    作为参考,这样一个复杂的正则表达式是

    62212[6-9]|6221[3-9]|622[1-8]|62291|62292[1-5]

    【讨论】:

      猜你喜欢
      • 2023-03-17
      • 2015-09-14
      • 2018-08-15
      • 2016-03-12
      • 1970-01-01
      • 2010-11-30
      • 2012-03-08
      • 2016-07-31
      • 2012-09-13
      相关资源
      最近更新 更多