不允许连续两个特殊字符,也不能在开头和结尾的正则表达式

5

我正在寻找一个字符串的正则表达式,它需要:

  1. 只包含A-Z a-z 0-9 _ - .
  2. 不能以_ - .开头或结尾。
  3. 不能包含连续的特殊字符或它们的组合。
  4. 最长36个字符,最短1个字符。

正确:

abcd-efgH
1
a
123
abc
abc-asd-123-asd_asd.asd

错误:

-
abc-_asd
abc.
abc.-asd
123123-123123-ads--asd
091-asdsad---

我搜索了一下,找到了以下内容:

/^(?!.*[^\na-z0-9]{2})(?=.*[a-z0-9]$)[a-z0-9].*$/gim

但这样可以允许所有特殊字符,而不仅限于我检查的那三个。
3个回答

5
您可以使用带有3个lookahead的正则表达式来匹配:
^(?![-_.])(?!.*[-_.]{2})(?!.*[-_.]$)[-\w.]{1,36}$

正则表达式演示

正则表达式细节:

  • ^:起始位置
  • (?![-_.]):负向前瞻,不允许在开头出现 [-_.]
  • (?!.*[-_.]{2}):负向前瞻,不允许任意两个连续 [-_.]
  • (?!.*[-_.]$):负向前瞻,不允许结尾出现 [-_.]
  • [-\w.]{1,36}:匹配一个 [-a-zA-Z0-9_.] 字符,长度范围:1 到 36
  • $:结束位置

2
...或者 ^(?!.*[-_.]{2})(?!.*[-_.]$)[^-_.][-\w.]{0,35}$ - Cary Swoveland
1
谢谢@CarySwoveland,但这也会匹配$abc,其中$不是允许的字符。但是^(?!.*[-_.]{2})(?!.*[-_.]$)[a-zA-Z0-9][-\w.]{0,35}$应该可以正常工作。 - anubhava
喝完早晨的咖啡后,我轻拍了一下自己的头。昨天有人告诉我,在 Java 中,与大多数语言不同,正则表达式必须匹配整个字符串。这是否意味着在这种情况下您不需要使用锚点? - Cary Swoveland
只有在使用“matches”方法中的正则表达式时,才不需要使用锚点。 - anubhava

1
你是指像这样的东西吗:
/^(?!.{37,})[a-z\d]+(?:[-._][a-z\d]+)*$/gim

请看在线 演示
  • ^ - 开始字符串定位符。
  • (?!.{37,}) - 否定先行断言,匹配长度超过37个字符的字符串。
  • [a-z\d]+ - 至少包含一个字符的字符组。
  • (?: - 打开非捕获组。
    • [-._] - 在此字符组内匹配一个字符。
    • [a-z\d]+ - 至少包含一个字符的字符组。
    • )* - 关闭非捕获组并将其匹配零次或多次。
  • $ - 结束字符串定位符。

0

我认为解决这个问题最简单和最直接的方法,以一种直观和逻辑的方式,是以下:

/^([a-z\d]|(?<![-_])(?<!^)[-_](?!$)){2,36}$/gim

解释非常简单。

第一个字符可以是字母或数字(|)第一个字符还可以是_-,因为前一个字符

a)既不是_也不是-

前一个字符的条件在负回溯中:(?<![-_])

这意味着,使用当前光标位置,负回溯(由(?<! P)模型表示,其中P是模式),只有当模式P不匹配时才可以(negative)适合(PS:回溯不移动光标) 在这种情况下,模式P只是[-_]。如果P后面不是-也不是_,则意味着-_是可选的选项!

b) _- 不在开头

紧接着我们有另一个负回顾,它仅测试文本的开头。P 就是 ^(表示文本开头的锚点)。回顾部分是 (?<!^)P 就是 ^

c) _- 不在结尾

最后,我们有一个负向前查找,但它出现在 [-_] 真实模式之后。唯一的语法区别是去掉了 "<" 字符(?!P,其中 P 是模式)。现在,正则表达式处理是在不移动光标的情况下向前搜索模式 P。如果模式失败,则是 OK(负面的!) 在这种情况下,我们有 (?!$),其中 P 是表示文本结尾的锚点 $

例如: ABCDEFGHIJKLMNOPQRSTU-XYZ01234_56789 匹配 但 ABCDEFGHIJKLMNOPQRSTU-_XYZ0123456789 不匹配 也不匹配 ABCDEFGHIJKLMNOPQRSTU-XYZ012345678_ 也不匹配 _BCDEFGHIJKLMNOPQRSTU-XYZ0123456789 在此处查看 在线链接

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接