用于验证用户名的正则表达式

我正在尝试创建一个正则表达式来根据以下条件验证用户名:

  1. 只包含 字母数字字符, 下划线
  2. 下划线和点不能在 结束开始 用户名(例如 _username/username_/.username/username.)。
  3. 下划线和点不能是 紧挨着(例如 user_.name)。
  4. 下划线或点不能多次使用 排成一排(例如 user__name/user..name)。
  5. 字符数必须在8到20之间。

这就是我到目前为止所做的; 听起来它强制执行了所有的标准规则 但是第五条规则。我不知道怎么把第五条加进去:

 ^[a-zA-Z0-9]+([._]?[a-zA-Z0-9]+)*$
157523 次浏览

I guess you'd have to use Lookahead expressions here. http://www.regular-expressions.info/lookaround.html

Try

^[a-zA-Z0-9](_(?!(\.|_))|\.(?!(_|\.))|[a-zA-Z0-9]){6,18}[a-zA-Z0-9]$

[a-zA-Z0-9] an alphanumeric THEN (

_(?!\.) a _ not followed by a . OR

\.(?!_) a . not followed by a _ OR

[a-zA-Z0-9] an alphanumeric ) FOR

{6,18} minimum 6 to maximum 18 times THEN

[a-zA-Z0-9] an alphanumeric

(First character is alphanum, then 6 to 18 characters, last character is alphanum, 6+2=8, 18+2=20)

Err sorry I generated this from my own library and it uses the syntax valid for Dart/Javascript/Java/Python, but anyway, here goes:

(?:^)(?:(?:[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKlMNOPQRSTUVWXYZ0123456789]){1,1})(?!(?:(?:(?:(?:_\.){1,1}))|(?:(?:(?:__){1,1}))|(?:(?:(?:\.\.){1,1}))))(?:(?:(?:(?:[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKlMNOPQRSTUVWXYZ0123456789._]){1,1})(?!(?:(?:(?:(?:_\.){1,1}))|(?:(?:(?:__){1,1}))|(?:(?:(?:\.\.){1,1}))))){6,18})(?:(?:[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKlMNOPQRSTUVWXYZ0123456789]){1,1})(?:$)

My library code:

var alphaNumeric = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "l", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"];
var allValidCharacters = new List.from(alphaNumeric);
allValidCharacters.addAll([".", "_"]);


var invalidSequence = (r) => r
.eitherString("_.")
.orString("__")
.orString("..");


var regex = new RegExpBuilder()
.start()
.exactly(1).from(alphaNumeric).notBehind(invalidSequence)
.min(6).max(18).like((r) => r.exactly(1).from(allValidCharacters).notBehind(invalidSequence))
.exactly(1).from(alphaNumeric)
.end()
.getRegExp();

My library: https://github.com/thebinarysearchtree/RegExpBuilder

A slight modification to Phillip's answer fixes the latest requirement

^[a-zA-Z0-9]([._](?![._])|[a-zA-Z0-9]){6,18}[a-zA-Z0-9]$

This one should do the trick:

if (Regex.IsMatch(text, @"
# Validate username with 5 constraints.
^                          # Anchor to start of string.
# 1- only contains alphanumeric characters , underscore and dot.
# 2- underscore and dot can't be at the end or start of username,
# 3- underscore and dot can't come next to each other.
# 4- each time just one occurrence of underscore or dot is valid.
(?=[A-Za-z0-9]+(?:[_.][A-Za-z0-9]+)*$)
# 5- number of characters must be between 8 to 20.
[A-Za-z0-9_.]{8,20}        # Apply constraint 5.
$                          # Anchor to end of string.
", RegexOptions.IgnorePatternWhitespace))
{
// Successful match
} else {
// Match attempt failed
}

As much as I love regular expressions I think there is a limit to what is readable

So I would suggest

new Regex("^[a-z._]+$", RegexOptions.IgnoreCase).IsMatch(username) &&
!username.StartsWith(".") &&
!username.StartsWith("_") &&
!username.EndsWith(".") &&
!username.EndsWith("_") &&
!username.Contains("..") &&
!username.Contains("__") &&
!username.Contains("._") &&
!username.Contains("_.");

It's longer but it won't need the maintainer to open expresso to understand.

Sure you can comment a long regex but then who ever reads it has to rely on trust.......

^(?=.{8,20}$)(?![_.])(?!.*[_.]{2})[a-zA-Z0-9._]+(?<![_.])$
└─────┬────┘└───┬──┘└─────┬─────┘└─────┬─────┘ └───┬───┘
│         │         │            │           no _ or . at the end
│         │         │            │
│         │         │            allowed characters
│         │         │
│         │         no __ or _. or ._ or .. inside
│         │
│         no _ or . at the beginning
│
username is 8-20 characters long

If your browser raises an error due to lack of negative look-behind support, use the following alternative pattern:

^(?=[a-zA-Z0-9._]{8,20}$)(?!.*[_.]{2})[^_.].*[^_.]$

^[a-z0-9_-]{3,15}$

^ # Start of the line

[a-z0-9_-] # Match characters and symbols in the list, a-z, 0-9, underscore, hyphen

{3,15} # Length at least 3 characters and maximum length of 15

$ # End of the line

private static final Scanner scan = new Scanner(System.in);


public static void main(String[] args) {
int n = Integer.parseInt(scan.nextLine());
while (n-- != 0) {
String userName = scan.nextLine();
String regularExpression = "^[[A-Z]|[a-z]][[A-Z]|[a-z]|\\d|[_]]{7,29}$";
if (userName.matches(regularExpression)) {
System.out.println("Valid");
} else {
System.out.println("Invalid");
}
}
}
^(?=.{4,20}$)(?:[a-zA-Z\d]+(?:(?:\.|-|_)[a-zA-Z\d])*)+$

You can test the regex here

function isUserName(val){
let regUser=/^[a-zA-Z0-9](_(?!(\.|_))|\.(?!(_|\.))|[a-zA-Z0-9]){6,18}[a-zA-Z0-9]$/;
if(!regUser.test(val)){
return 'Name can only use letters,numbers, minimum length is 8 characters';
}
}
const regex = /^moe_(app|lab)[A-Za-z0-9]{3}$/;
const str = `moe_app_baa`;
let m;


if ((m = regex.exec(str)) !== null) {
// The result can be accessed through the `m`-variable.
m.forEach((match, groupIndex) => {
console.log(`Found match, group ${groupIndex}: ${match}`);
});
}

Stumbled upon this question in another one. Seems not necessary to use that many lookarounds. Following a bit shorter pattern with use of \w which is a short for word character and commonly preset to [A-Za-z0-9_]. To get rid of the underscore, [^\W_] can be used to match [A-Za-z0-9].

^[^\W_](?!.*?[._]{2})[\w.]{6,18}[^\W_]$
  • ^[^\W_] one letter or digit at the start
  • (?!.*?[._]{2}) negative lookahead to disallow __ ._ _. ..
    (for reduing steps on longer inputs, a lazy quantifier is used in .*?)
  • [\w.]{6,18} 6 to 18 characters that can be letters, digits, _ and .
  • [^\W_]$ ending in another letter or digit

See this demo at regex101 (further explanation on the right side)

Note: \w depending on environment/settings can further contain unicode letters and digits.