【问题标题】:How do I match a pattern with alphabets AND numbers, but not if it contains only alphabets?如何匹配带有字母和数字的模式,但如果它只包含字母则不匹配?
【发布时间】:2018-05-11 15:58:43
【问题描述】:

我正在尝试使用正则表达式来检查字符串中的字母和数字,但如果字符串仅包含字母,则它不应该匹配。这是一个javascript代码。是否应该使用前瞻?

应该匹配: 1234567 a1b2c3d4e5 1a2b3c4d5e

不应匹配: abcdefg

编辑:感谢@balsick,这个问题已经得到解答。这是要使用的正则表达式 - (([a-zA-Z0-9]+\d+[a-zA-Z0-9])|(\d+[a-zA-Z0-9]+\d ))+

我确实有一个后续问题:可以在这个正则表达式中添加长度约束吗?例如:我只想匹配 10-20 个字母/数字的字符串。

【问题讨论】:

  • 堆栈溢出不会很受欢迎。展示您的尝试并标记语言或工具。
  • 这是一个很好的问题,非常适合 SO。我不明白反对票...

标签: javascript regex


【解决方案1】:

试试这个:

((\w+\d+\w*)|(\d+\w+\d*))+

\w 查找字母

\d 查找数字

+ 表示至少一个

* 表示零个或多个

|是 or 运算符

编辑(改进)

我为您的主要问题找到了更好的解决方案。它比@balsick 的解决方案更短更快,并且不会捕获_ 字符:

([a-zA-Z]*\d[a-zA-Z]*)+

您希望限制字符串长度的愿望很难用正则表达式来解决。有一些选项可以限制匹配的数量。例如:

a{5}a{2,} 正好五个、两个或更多

a{1,3}在一到三之间

但这不适用于上层正则表达式,因为每个子匹配都是

  • 一个或多个字母与数字组合,例如:aa1,
  • 一个数字与一个或多个字母组合,例如:1aaa,
  • 一个或多个字母与一个数字和一个或多个字母组合,例如:a1aa
  • 或单个数字,例如:1

如果你有一个像 a1b2c3d4e5 这样的匹配,它由以下子匹配组成:a1b2c3d4e5

虽然匹配由 10 个字符组成,但使用量词 {10,20} 而不是最后一个加号将不起作用,因为子匹配的实际数量是 5 而不是 10。

我认为您必须使用上面的正则表达式,然后以编程方式检查每个匹配项的长度。

伪代码:

foreach (var match in matches) {
    if (match.Value.length < 21 && match.Value.length > 9) {
        doSomething();
    }
}

或者,如果你有可能使用 Linq,你可以这样做:

var filteredMatches = matches.Filter(match => match.Value.length < 21 && match.Value.length > 9)

【讨论】:

  • 这并不完全正确,因为您也在考虑_(([a-zA-Z0-9]+\d+[a-zA-Z0-9]*)|(\d+[a-zA-Z0-9]+\d*))+ 更正确
  • 感谢@balsick!这就像一个魅力。有没有办法为您拥有的正则表达式添加长度约束?例如:我只想匹配那些介于 10-20 个字母/数字之间的字符串。
  • @anil-premkumar 我已经更新了我的答案。我希望这会对你有所帮助。
  • 我刚刚意识到我的评论是错误的 :) 方括号中有一个不应该存在的 0-9。此外,正则表达式可以像这样简化(([a-zA-Z]+\d+)|(\d+[a-zA-Z]+))+
【解决方案2】:

您可以断言字符串^ 的开头,使用带有alternation 的非捕获组(?: 来匹配数字\d| 一个或多个字符后跟一个数字@987654328 @。这样可以确保您至少有 1 位数字,并且您也可以以字符开头。

然后,对于正则表达式的最后一部分,您可以匹配零个或多个数字和字符 [a-z\d]*,直到字符串 $ 的结尾。

要匹配大小写字符,您可以使用 [a-z] 和不区分大小写的标志 /i

^(?:\d|[a-z]+\d)[a-z\d]*$

let pattern = /^(?:\d|[a-z]+\d)[a-z\d]*$/i;
const strings = [
  "a1b2c3d4e5",
  "1a2b3c4d5e",
  "abcdefg",
  "1234567"
];
strings.forEach((s) => {
  console.log(s + " ==> " + pattern.test(s));
});

如果您想确保匹配包含 10 到 20 个字母数字字符,您可以使用正向预测:

^(?=[a-z\d]*\d)[a-z\d]{10,20}$

let pattern = /^(?=[a-z\d]*\d)[a-z\d]{10,20}$/i;
const strings = [
  "a1b2c3d4e5",
  "1a2b3c4d5e",
  "1234567",
  "abcdefg",
  "1234567",
  "12112121121fffdfdfdfdfdfdfd",
  "fdfddfdfdffdfdf5ffrtgr54f345f453f3ff"
];
strings.forEach((s) => {
  console.log(s + " ==> " + pattern.test(s));
});

【讨论】:

    【解决方案3】:

    使用来自@balsick 的输入更新答案

    使用前瞻正则表达式:

    ^(?=[A-Za-z\d]*\d)[A-Za-z\d]*$
    

    Demo

    【讨论】:

    • 这实际上并没有像您期望的那样工作,因为它也匹配像_____3这样的字符串。也许你的意思是^(?=[A-Za-z\d]*\d)[A-Za-z\d]*$
    • Lookaheads 和 lookbehinds 在时间上很昂贵,并且并非每种编程语言都支持
    • @balsick,我同意。请发布您的正则表达式作为答案,我将删除我的。
    猜你喜欢
    • 1970-01-01
    • 2019-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-09
    相关资源
    最近更新 更多