Is there a better way to write a regex that does not match on leading and trailing spaces along with a character limit?
我的瑞格鞋是…
1
| ^[A-z0-9]*[A-z0-9\s]{0,20}[A-z0-9]*$ |
此regex的最终目标是不允许使用前导空格和尾随空格,同时将输入的字符限制为20,而上面的regex在这方面做得不好。
我发现了一些类似的问题,最接近的问题是如何用regex验证用户名?但它没有限制字符数。这确实解决了前导和尾随空间的问题。
我也看到了一种使用否定和另一种消极展望的方法,但这对我来说不是很好。
有没有更好的方法可以用20个字符的限制来写上面的regex?允许的字符的重复非常难看,尤其是当允许的字符列表较大且特定时。
- 这个案子敏感吗?[A-z]与[A-Za-z]不同。
- 说明@onlinecop的评论:regex a-z和a-za-z之间的区别
- @在线警察我不知道…
- @罗宾谢谢你的链接。这有帮助。
更新:
我更喜欢这个。我们使用负向前看来确保字符串末尾没有^\s(字符串开头的空白)或\s$空白。然后匹配1个字母数字字符。我们重复1-20次。
1
| /^(?:(?!^\s|\s$)[a-z0-9\s]){1,20}$/i |
演示
1 2 3 4 5 6 7 8 9 10
| ^ (?# beginning of string)
(?: (?# non-capture group for repetition)
(?! (?# begin negative lookahead)
^\s (?# whitespace at beginning of string)
| (?# OR)
\s$ (?# whitespace at end of string)
) (?# end negative lookahead)
[a-z0-9\s] (?# match one alphanumeric/whitespace character)
){1,20} (?# repeat this process 1-20 times)
$ (?# end of string) |
初始:
我在字符串的开头((?!...))使用了一个负向前视,以确保我们不会从空白开始。然后我们检查0-19个字母数字(由于i修饰符不区分大小写)或空白字符。最后,我们确保以纯字母数字字符(没有空格)结尾,因为我们不能在javascript中使用lookbehind。
1
| /^(?!\s)[a-z0-9\s]{0,19}[a-z0-9]$/i |
- 我不太熟悉?你能给我一个简短的解释吗?(?)!^s s$)实际上是这样工作的?如果是这样,我就不知道了。
- @dalawh (?:...)是一个非捕获组,我们需要一个组来执行重复,?:只是防止不必要的捕获组。负的lookahead执行零长度断言(换句话说,它只是检查以确保下一个字符不匹配)。由于此lookahead位于重复的非捕获组中,因此我们每次检查一次以确保不查看任何前导/尾随空格。如果我们在PCRE中,我们可以使用负先行和负先行……而不是重复的负先行。
- 旁注:重复的负向前看比原来的解决方案效率低。这是因为它断言每个字符都是先行的,而不仅仅是字符串的开头/结尾。但是,断言为1个字符,重复次数限制在20次……不应该被注意到。我更喜欢这个解决方案,因为它使用字符类和一个明显的重复范围{1,20}。
- 我想我的下一个问题是捕获的用途是什么?我有一个团体的概念。我能找到的最好的例子是stackoverflow.com/questions/3512471/non-captured-group。似乎捕获用于对捕获的组进行进一步的工作,因此如果不想进行任何其他工作,则使用非捕获组?那是我最迷路的地方。
- @dalawh您通常将事物分组以便进行交替(|)或捕获/引用(所有组捕获,除非它们不捕获(?:...))。引用的一个例子是/([a-z])\1+/。这将与aaa相匹配(因为a被捕获,所以\1=== ), but not abc. You can also use this in substitutions, so matching (foo)。*并用\1bar替换它,将foofail更改为foobar。因为在我的示例中我们不需要引用任何内容,所以不需要捕获它(所以我习惯于不捕获)。不过,这不是最大的交易,因为我们不引用任何其他内容。
- 举个例子来解释我所说的"不是最大的交易"。如果我们匹配(abc|xyz)(foo|bar)并想用foo或bar替换它,我们需要使用替换\2(这会把abcfoo改为foo)。当"第一个"的捕获组从未被引用时,引用"第二个"捕获组感觉很奇怪……所以我将匹配(?:abc|xyz)(foo|bar),替换\1。
- 谢谢你的解释。你知道这些类型的regex是否与c一起工作吗?我不太确定这两者之间有多不同。
- @达拉对我来说很好。
- 谢谢你的帮助
嗯,如果您需要排除单个字符的文本,我将使用:
1
| ^[A-z0-9][A-z0-9\s]{0,18}[A-z0-9]$ |
如果一个字符也可以接受:
1
| ^[A-z0-9](?:[A-z0-9\s]{0,18}[A-z0-9])?$ |
使用此模式^(?!\s).{0,20}(?。
- ^(?!\s)行首看不到空格
- .{0,20}后接0到20个字符
- (?以非空格字符结尾
演示
或者这个模式^(\S.{0,18}\S)?$。演示
- 小心,不要在javascript中掉以轻心,第二个模式不接受一个字符串。
\S匹配非空白字符。因此,这应该与您要查找的内容相匹配:
^\S.{0,18}\S$
也就是说,一个非空格字符\S,后面跟着18个任意类型的字符.(空格与否),最后是一个非空格字符。
上述regex的唯一限制是该值必须至少为2个字符。如果需要允许1个字符,可以使用:
^\S(.{0,18}\S)?$
如果您希望验证用户名(如您所暗示的,但没有明确声明),那么您可能希望只允许数字、字母和下划线。在这种情况下,^\w{1,20}$就足够了。
- 最小字符为0,因此如果为空,则应该通过。
- ^\(S(.{0,18}\S)?)?$将允许它为空
- 我认为您的regex将输入限制为22个字符,而不是20个字符。
- 您知道字符范围[a-z]包括字符[\]^_`吗?
我想我会这样做:
1 2 3 4 5
| input = input.trim().replace(/\s+/, ' ');
if (input.length > MAX_INPUT_LENGTH ||
! /^[a-z ]+$/i.match(input) ) {
# raise exception?
} |