【问题标题】:RegEx for an invoice format发票格式的正则表达式
【发布时间】:2010-12-24 19:05:14
【问题描述】:

我对正则表达式很陌生,我正在尝试创建一个正则表达式来验证发票格式。

模式应该是: JjYy(所有 4 个字符都是合法的),使用了 0、2 或 4 次 例如根本没有 Y 是有效的,YY 是有效的,YYYY 是有效的,但是 YYY 应该会失败。 随后是一系列 0 重复 3 到 10 次。 整体不得超过 10 个字符。

例子: JyjY000000 是有效的(虽然很奇怪) YY000 有效 000000 有效 jjj000 无效 jjjj0 无效

我从here 学到了一些基础知识,但是我的正则表达式在不应该的时候失败了。有人可以帮忙改进吗?

到目前为止,我的正则表达式是:[JjYy]{0}|[JjYy]{2}|[JjYy]{4}[0]{3,10}

以下也失败了:[JjYy]{0|2|4}[0]{3,10}

【问题讨论】:

  • jJyY 部分的最大长度限制是 10 吗?
  • +1 因为你快到了,你向我们展示了你到目前为止所做的事情
  • 谢谢,PP :)。 JjYy 确实是长度限制 10 的一部分。顺便说一句,我需要在 C# 项目中使用正则表达式,但我不知道正则表达式引擎之间的差异在哪里。
  • 您能否发布一个示例,其中我的正则表达式在 jJyY 部分之前允许 0

标签: regex


【解决方案1】:

由于您需要总长度不超过 10 个字符,我认为您必须分别处理三种前缀:

0{3,10}|[JjYy]{2}0{3,8}|[JjYy]{4}0{3,6}

【讨论】:

  • 更好的是,不要使用正则表达式来做到这一点。正则表达式不是计算字符串中字符数的最佳方法。
  • 我会说正则表达式非常适合验证字符串是否与指定格式匹配,并且长度通常是任何有效格式的一部分。您必须使用“或”(或其他答案之一所示的否定前瞻)意味着格式比您想要的更复杂,但这并不意味着您应该使用单独的查看。我强烈建议将所有验证保存在一个地方 - 正则表达式 - 因为从维护的角度来看这更好。
  • 如何确保字符串不超过 10 个字符以开始使用负前瞻?我已经用这样的解决方案更新了我的答案。
  • 我接受了你的回答,因为你的回答是第一个符合我正在寻找的所有条件的人:)。
【解决方案2】:

怎么样:

^([JjYy]{2}){0,2}0{3,10}$

要检查长度是否为 10 个字符或更少,请使用字符串长度函数而不是正则表达式 - 不要用螺丝刀敲钉子等等。

测试:

#!perl
use warnings;
use strict;

my $re = qr/^([JjYy]{2}){0,2}0{3,10}$/;

my %tests = qw/JyjY000000 valid
           YY000 valid
           000000 valid
           jjj000 invalid
           jjjj0 invalid/;

for my $k (keys %tests) {
    print "$k is ";
    if ($k =~ /$re/) {
        print "valid";
    } else {
        print "invalid";
    }
    print " and it should be $tests{$k}.\n";
}

生产

jjjj0 无效,应该是无效的。 YY000 有效,应该有效。 JyjY000000 有效,应该有效。 jjj000 无效,应该是无效的。 000000 是有效的,它应该是有效的。

【讨论】:

  • 你打败了我——如果不是因为那些括号,两者都是一样的:)
  • 人们经常抱怨我回答太快。
  • YYYY0000000000 匹配为有效,不应超过十个字符。
  • 我建议为此计算字符串的长度。
【解决方案3】:
([jJyY]{2}){0,2}0{3,10}

如果总长度限制包括jJyY 部分,您可以用否定的前瞻来检查它,以确保字符串中以(?![jJyY0]{11,}) 开头的字符不超过10 个

\b(?![jJyY0]{11,})([jJyY]{2}){0,2}0{3,10}\b

【讨论】:

  • YYYY0000000000 有效,不应超过十个字符。
  • 如果总长度限制包含jJyY部分,您可以用否定的前瞻来检查它,以确保字符串中以(?![jJyY0]{11,})开头的字符不超过10个
  • jJyY0 部分可以在 JjYy 之前使用 0,这应该是无效的。但是,它与我想要的非常接近,谢谢。
  • 我喜欢消极的看法,但你可以让它更简单。通过前瞻,您只对长度真正感兴趣,因为您正在使用正则表达式的其余部分检查格式,因此您可以制作您的模式:(?!.{11,})([jJyY]{2}){0,2}0{3,10}
  • 我并不是为了被接受而“战斗”——只是想确保我的正则表达式确实是正确的 :)
【解决方案4】:

这可能取决于您使用什么来实现正则表达式。例如,前几天我发现 Notepad++ 只支持一些基本的操作符。管道之类的东西不是核心正则表达式标准的一部分。

我建议这样:

([JjYy]{2}([JjYy]{2})?)?[0]{3,10}

如果您使用的是编程语言,则需要使用字符串长度函数来验证长度。

编辑:实际上,您应该能够通过区分不同的情况来验证长度:

([0]{3,10})|([JjYy]{2}[0]{3,8})|([JjYy]{4}[0]{3,6})

【讨论】:

    【解决方案5】:

    您希望将字符串限制为 10 个字符。因此,为了做到这一点,您必须考虑哪些有效组合将构成 10 个字符。

    因此有效的组合是:

    • 0000000000
    • 000
    • cc00000000
    • cc000
    • cccc000000
    • cccc000

    因此,包含所有这些的表达式将是: /0{3,10}|[JY]{2}0{3,8}|[JY]{4}0{3,6}/i

    不区分大小写的匹配就足够了,尽管您确实可以通过明确说出 /[JjYy]/ 而不是 /[JY]/i 从某些正则表达式引擎获得额外的性能。

    【讨论】:

    • 该表达式接近标记,但它仅在 0 处失败。
    • 可能是因为您不想在 C# 正则表达式中使用斜杠 (/)。在 Perl、Awk 和 sed 中,通常在正则表达式周围加上斜线。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-09
    • 1970-01-01
    • 2020-06-24
    • 1970-01-01
    • 1970-01-01
    • 2016-05-04
    相关资源
    最近更新 更多