简体   繁体   中英

How to write a regular expression that allows certain characters to only be repeated once?

I am trying to make a regular expression that matches the following characteristics:

  • n maximum total characters;
  • allows [az] and [AZ] any repeated number of times within the string;
  • allows [_.] but cannot be adjacent in the string;
  • cannot start with _ or .

So, for example

  • foo — good
  • foo_bar — good
  • foo__bar — bad (repeats _ )
  • foo_bar_baz — good
  • foo_bar.baz — good
  • foo_.bar — bad (adjacent _ and . )
  • _foo — bad (leading _
  • .foo — bad (leading . )

I am using JS. I've been trying to figure this out but have had no luck. Hoping someone can help me save some time! Thank you.

Start with at least one alphabetic. Follow that by an optional special/punctuation character. Repeat as many times as necessary until the end of string.

^([a-zA-Z]+[_.]?)+$
^([a-zA-Z]+[_.]?)[a-zA-Z]+$ // disallow special character at end

Handle the length test separately. Is there a reason it needs to be included in the regex? You could handle it with a lookahead if you strictly require it.

^(?=.{6,10}$)([a-zA-Z]+[_.]?)+$ // for example, length between 6 and 10

The other regexes provided, while they may work, are overly complicated and inefficient. The following regex will match what you want (excluding the length check as that's most efficiently done with .length on the string itself.

/^(?:[a-zA-Z]+[_.]?)+$/

It simply says, find at least one letter (or more), and then an optional _ or . , then find at least one letter (or more), and an optional _ or . , etc.

Here is a simple non-lookahead based regex:

/^[a-z](?:[_.]?[a-z])*$/gmi

RegEx Demo

This will only allow a letter at start and end and it will not allow adjacent DOT or underscore characters.

All in a single regex

/^[az](?:[az]|[_.](?![_.])){0,19}$/i

Commented

 # N = 20, range: 1 - 20
 # ------------------------
 ^                 # BOS
 [a-z]             # Start with letter
 (?:               # Count group
      [a-z]             # a - z
   |                  # or
      [_.]              # underscore or dot
      (?! [_.] )        # if not followed by same
 ){0,19}           # End count, 0 to N-1
 $                 # EOS 

Test sample:

foo
foo_bar
foo__bar
foo_bar_baz
foo_bar.baz
foo_.bar
_foo
.foo

Benchmark:

Regex1:   ^[a-z](?:[a-z]|[_.](?![_.])){0,19}$
Options:  < m - i >
Completed iterations:   50  /  50     ( x 1000 )
Matches found per iteration:   4
Elapsed Time:    0.67 s,   673.02 ms,   673023 µs

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM