2

I don't know Regex,

But I need to have regex expression for evaluation of ClassName.PropertyName?

Need to validate some values from appSettings for being compliant with ClassName.PropertyName convention

"ClassName.PropertyName" - this is the only format that is valid, the rest below is invalid:

"Personnel.FirstName1"   <- the only string that should match
"2Personnel.FirstName1"
"Personnel.33FirstName"
"Personnel..FirstName"
"Personnel.;FirstName"
"Personnel.FirstName."
"Personnel.FirstName   "
" Personnel.FirstName"
" Personnel. FirstName"
" 23Personnel.3FirstName"

I have tried this (from the link posted as duplicate):

 ^\w+(.\w+)*$

but it doesn't work: I have false positives, e.g. 2Personnel.FirstName1 as well as Personnel.33FirstName passes the check when both should have been rejected.

Can someone help me with that?

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
monstro
  • 6,254
  • 10
  • 65
  • 111

2 Answers2

5

Let's start from single identifier:

  1. Its first character must be letter or underscope
  2. It can contain letters, underscopes and digits

So the regular expression for an identifier is

[A-Za-z_][A-Za-z0-9_]*

Next, we should chain identifier with . (do not forget to escape .) an indentifier followed by zero or more . + identifier:

^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$

In case it must be exactly two identifiers (and not, say abc.def.hi - three ones)

^[A-Za-z_][A-Za-z0-9_]*\.[A-Za-z_][A-Za-z0-9_]*$

Tests:

string[] tests = new string[] {
  "Personnel.FirstName1",  // the only string that should be matched
  "2Personnel.FirstName1",
  "Personnel.33FirstName",
  "Personnel..FirstName",
  "Personnel.;FirstName",
  "Personnel.FirstName.",
  "Personnel.FirstName   ",
  " Personnel.FirstName",
  " Personnel. FirstName",
  " 23Personnel.3FirstName",
} ;

string pattern = @"^[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_]*)*$";

var results = tests
  .Select(test => 
    $"{"\"" + test + "\"",-25} : {(Regex.IsMatch(test, pattern) ? "matched" : "failed")}"");

Console.WriteLine(String.Join(Environment.NewLine, results));

Outcome:

"Personnel.FirstName1"    : matched
"2Personnel.FirstName1"   : failed
"Personnel.33FirstName"   : failed
"Personnel..FirstName"    : failed
"Personnel.;FirstName"    : failed
"Personnel.FirstName."    : failed
"Personnel.FirstName   "  : failed
" Personnel.FirstName"    : failed
" Personnel. FirstName"   : failed
" 23Personnel.3FirstName" : failed

Edit: In case culture specific names (like äöü.FirstName) should be accepted (see Rand Random's comments) then [A-Za-z] range should be changed into \p{L} - any letter. Exotic possibility - culture specific digits (e.g. Persian ones - ۰۱۲۳۴۵۶۷۸۹) can be solved by changing 0-9 into \d

// culture specific letters, but not digits 
string pattern = @"^[\p{L}_][\p{L}0-9_]*(?:\.[\p{L}_][\p{L}0-9_]*)*$";

If each identifier should not exceed sertain length (say, 16) we should redesign initial identifier pattern: mandatory letter or underscope followed by [0..16-1] == {0,15} letters, digits or underscopes

[A-Za-z_][A-Za-z0-9_]{0,15}

And we have

string pattern = @"^[A-Za-z_][A-Za-z0-9_]{0,15}(?:\.[A-Za-z_][A-Za-z0-9_]{0,15})*$";
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • 1
    Another thing, was just playing around. It also fails to validate length `Name 'superlongclassname' exceeds the maximum length allowed in metadata.` – Rand Random May 28 '18 at 13:37
  • Was to fast on the delete comment button, only read "In case culture specific…" and deleted my comment - only saw later that you mentioned my comment. Sorry. – Rand Random May 28 '18 at 13:38
0
^[A-Za-z]*\.[A-Za-z]*[0-9]$

or

^[A-Za-z]*\.[A-Za-z]*[0-9]+$

if you need more than one numerical character in the number suffix

Ares
  • 1,356
  • 1
  • 9
  • 22