【问题标题】:Regex to match only when expression match is no more than 12 characters long正则表达式仅在表达式匹配长度不超过 12 个字符时匹配
【发布时间】:2015-12-23 16:32:39
【问题描述】:

我正在尝试创建一个与以下正则表达式匹配的正则表达式 (Java/JavaScript),但前提是总共少于 13 个字符(并且至少为 4 个)。

(COT|MED)[ABCD]?-?[0-9]{1,4}(([JK]+[0-9]*)|(\DDD)?)   ← 最初发布

(COT|MED)[ABCD]?-?[0-9]{1,4}(([JK]+[0-9]*)|(\ [A-Z]+)?)

这些值应该(并且确实)匹配:

MED-123
COTA-1224
MED4
COTB-892K777
MED-33 DDD
MED-234J5678

此值匹配,但我不希望它匹配(我只想匹配总共少于 12 个字符):

COT-1111J11111111111111

http://regexr.com/3bs7bhttp://regexr.com/3bsfv

我尝试将我的表达式分组并将{4,12} 放在最后,但这只会使其查找整个表达式匹配的 4 到 12 个实例。

我觉得我错过了一些简单的东西......提前感谢您的帮助!

【问题讨论】:

  • 试试(COT|MED)[ABCD]?-?[0-9]{1,4}(([JK]+[0-9]{1,4})|( DDD)?)\b。见demo
  • 另外,你可以试试(?!\S{13})(COT|MED)[ABCD]?-?[0-9]{1,4}(([JK]+[0-9]*)|(\ DDD)?)。对你有用吗?
  • 这可能是在这种情况下,尝试过多地投入正则表达式是不值得的。为什么不只做正则表达式,然后如果你得到一个匹配,采取第二步检查匹配序列的长度(matcher.group(0).length() < 12在Java中,类似在js中)?
  • @stribizhev 您的第二条评论(否定前瞻)按预期工作-就像接受的答案一样-您应该将此作为答案而不是评论!
  • @yshavit 不幸的是,多合一正则表达式是我唯一可用的选项,否则,正如您所建议的,只检查匹配的长度肯定会容易得多

标签: javascript java regex


【解决方案1】:

我尝试将我的表达式分组并将 {4,12} 放在最后,但是 这只是让它查找整个表达式的 4 到 12 个实例 匹配。

这会查找整个表达式的 4 到 12 个实例,因为您没有添加单词边界 \b。您的正则表达式工作正常,只需添加一个单词边界即可实现您想要的结果。看看这个DEMO

您的正则表达式似乎很笨拙,看起来有点难以阅读。它也非常限于某些字符,例如JK,除非您希望它是那样的。对于更一般的模式,您可以查看此

(COT|MED)[AB]?-?[\dJK]{1,8}(\s+D{1,3})?\b

(COT|MED): 匹配COTMED

[AB]?: 匹配可选的 A 或 B,因为存在 ?

-?: 匹配 -,这也是可选的

[\dJK]{1,8}: 匹配numberJK,长度至少为一个字符,最多为八个字符。

(\s+D{1,3})?: 匹配空格或 D 至少 1 次,最多 3 次,这是可选的

\b: 关于你的问题,这似乎是最重要的,它为已经匹配的单词创建了一个边界。这意味着任何超出匹配模式的内容都不会被捕获。

在此处查看演示 DEMO2

【讨论】:

  • 感谢您的详细回答,我正准备接受,但这不是解决方案。查看您的第一个演示链接的最后一个测试字符串,该值已与我最初的示例不同。删除正则表达式末尾的\b,该行有部分匹配,而我在该行上的测试字符串是完全匹配的,因此\b 正在对该部分匹配做出反应。关于正则表达式,是的,它很难阅读并且非常有限,但不幸的是,我正在处理的就是这种情况。我简化了一点,应该写 [A-Z]+ 而不是 DDD - 这排除了 D{1,3}
  • 检查得很好,除了 `\b' 之外,链接中的是您的模式。它匹配最后一个字符串的一部分。除非你没有很好地发布模式。如需更多确认,请尝试测试您的模式以在另一个正则表达式引擎中进行测试,它会产生相同的结果
  • 根据您的正则表达式测试“COT-1111J1111111111111”...它匹配,但它不应该满足我的问题
  • 我现在才这样做,但它不匹配。用 demo2 测试它
  • 好的,demo2 有效,但它在正则表达式中假设 {1,8} 和 {1,3},这不适用于我的情况。谢谢
【解决方案2】:

你正在寻找的答案是

(?!\S{13})(?:COT|MED)[ABCD]?-?\d{1,4}(?:[JK]+\d*|(?: [A-Z]+)?)

regex demo

请注意,几乎不可能检查不是整个字符串或内部有空格的短语的长度,因为边界有点“模糊”。因此,(?!\S{13}) 是一种解决方法,它只是确保您没有没有空格且长度为 13 个字符或更长的字符串。

正则表达式分解:

  • (?!\S{13}) - 检查后面的子字符串是否不包含 13 个非空白字符
  • (?:COT|MED) - Any of the values in the alternation (COTorMED`)
  • [ABCD]?-? - 可选ABCD,然后是可选的-
  • \d{1,4} - 1 到 4 位数字
  • (?:[JK]+\d*|(?: [A-Z]+)?) - 一组 2 个选项:
    • [JK]+\d* - JK,1 次或更多次,然后是 0 位或更多位
    • (?: [A-Z]+)? - 可选空格和 1 个或多个拉丁大写字母

【讨论】:

    【解决方案3】:

    您可以使用负前瞻:

    (?!.{13,})(COT|MED)[ABCD]?-?[0-9]{1,4}(([JK]+[0-9]*)|(\ DDD)?)
    

    由于您的表达式已经确保匹配以 COT 或 MED 开头并且之后至少有一位数字,因此它已经保证至少有 4 个字符

    【讨论】:

    • 这是为我做的——谢谢!这是与我的测试字符串一起使用的正则表达式:regexr.com/3bsg2
    【解决方案4】:

    正如answer 建议的那样,您可以这样解决:

    (?=(COT|MED)[ABCD]?-?[0-9]{1,4}(([JK]+[0-9]*)|(\ DDD)?))(?={4 , 12})
    

    【讨论】:

    • 这适用于许多服务器端正则表达式实现,但我认为 Javascript RegExp 不支持它,这是给定的关键字之一。
    • @PaulKienitz 无法确认或反驳这一点,因为我无法访问 javascript 文档 atm。我一有访问权限就会更新
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-29
    • 2021-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多