views:

130

answers:

2

The string should be 6 - 20 characters in length. And it should contain 1 Capital letter.

I can do this in code using C#

      string  st = "SomeString"

      Regex rg = new Regex("[A-Z]");
      MatchCollection mc = rg.Matches(st);

      Console.WriteLine("Total Capital Letters: " + mc.Count);

      if (mc.Count > 1)
      {
        return false;
      }

But what i really want is a Regular expression that will match my string if it only contains one capital. The string can start with a common letter and should have only letters.

Thanks In advance. (I did look at some of the other RegEx questions but they did not help).

+6  A: 

This one will match a string that contains lowercase letters, then a single capital letter, then more lowercase letters.

^[a-z]*[A-Z][a-z]*$

You can adjust the first and last parts to include other characters as necessary, depending on your required character domain.

For all strings of length 6 to 20, containing only letters and at most one capital letter, you can use lookaheads:

(?=^[a-zA-Z]{6,20}$)^[a-z]*[A-Z][a-z]*$
Welbog
Add a positive look ahead to enforce the 6-20 char limit
Simeon Pilgrim
This will actually accept any string with exactly one capital. This includes strings with no lower case chars.
torak
At first you didn't have the look ahead... now it's there, but I don't see a "edited x minutes ago". Am I losing my mind?
Timothy Khouri
@torak - No, it'll work if the Regex Options are not set to CaseInsensitive.
Timothy Khouri
I'm just really fast. :) Had to verify my regex was right before I posted the lookahead solution.
Welbog
@Timothy Khouri - In the original answer's the '*'s in "^[a-z]*[A-Z][a-z]*$" can match 0 or more. Now that the positive look ahead is added, it resolves the issue.
torak
You can shorten it: ^(?=.{6,20}$)[a-z]*[A-Z][a-z]*$
tiftik
I like your first regex. I would combine it with a separate length check. Lookaheads aren't part of real regexes anyway - and they're not especially fast either.
Chris Lercher
Thanks you so much. I tried the lookaheads but did not get far writing it myself. I will try to look at Welbog submission and reverse engineer. Thanks Again.
Phoenix
+2  A: 

regex

/(?=^\w{6,20}$)(?=\w*[A-Z])^\w+$/

tests

a                       # fail
aX                      # fail
ab                      # fail
aXb                     # fail
abc                     # fail
abXc                    # fail
abcd                    # fail
abcXd                   # fail
abcde                   # fail
abcdXe                  # pass
abcdef                  # fail
abcdeXf                 # pass
abcdefg                 # fail
abXcdefg                # pass
abcdefgh                # fail
abcXdefgh               # pass
abcdefghi               # fail
abcdXefghi              # pass
abcdefghij              # fail
abcdeXfghij             # pass
abcdefghijk             # fail
abcdefXghijk            # pass
abcdefghijkl            # fail
abcdefgXhijkl           # pass
abcdefghijklm           # fail
abcdefghXijklm          # pass
abcdefghijklmn          # fail
abcXdefghijklmn         # pass
abcdefghijklmno         # fail
abcdXefghijklmno        # pass
abcdefghijklmnop        # fail
abcdeXfghijklmnop       # pass
abcdefghijklmnopq       # fail
abcdefXghijklmnopq      # pass
abcdefghijklmnopqr      # fail
abcdefgXhijklmnopqr     # pass
abcdefghijklmnopqrs     # fail
abcdefghXijklmnopqrs    # pass
abcdefghijklmnopqrst    # fail
abcdefghiXjklmnopqrst   # fail
abcdefghijklmnopqrstu   # fail
abcdefghijXklmnopqrstu  # fail

regex explanation

NODE                     EXPLANATION
--------------------------------------------------------------------------------
  (?=                      look ahead to see if there is:
--------------------------------------------------------------------------------
    ^                        the beginning of the string
--------------------------------------------------------------------------------
    \w{6,20}                 word characters (a-z, A-Z, 0-9, _)
                             (between 6 and 20 times (matching the
                             most amount possible))
--------------------------------------------------------------------------------
    $                        before an optional \n, and the end of
                             the string
--------------------------------------------------------------------------------
  )                        end of look-ahead
--------------------------------------------------------------------------------
  (?=                      look ahead to see if there is:
--------------------------------------------------------------------------------
    \w*                      word characters (a-z, A-Z, 0-9, _) (0 or
                             more times (matching the most amount
                             possible))
--------------------------------------------------------------------------------
    [A-Z]                    any character of: 'A' to 'Z'
--------------------------------------------------------------------------------
  )                        end of look-ahead
--------------------------------------------------------------------------------
  ^                        the beginning of the string
--------------------------------------------------------------------------------
  \w+                      word characters (a-z, A-Z, 0-9, _) (1 or
                           more times (matching the most amount
                           possible))
--------------------------------------------------------------------------------
  $                        before an optional \n, and the end of the
                           string
macek