0

I'm trying to come up with a regex to validate the following to be true:

This Is A Cat

However, to evaluate the following to be false:

This is a cat

Or this to be false too:

This Is A cat (Note the 'c' is not upper case in Cat)

I'm trying in JavaScript, thought the following should work:

/(\b[A-Z][a-z]*\s*\b)+/

Here is my logic:

  1. Start at a word boundary
  2. Match an uppercase character
  3. Match zero or more lowercase characters
  4. Match zero or more spaces
  5. Match a word boundary
  6. Repeat the above one or more times

What is wrong with my thinking?

user1800556
  • 67
  • 1
  • 7

3 Answers3

1

If you only want to know if a string matches the condition, and don't care where it fails, you can check for either a lower case letter at the start of the string, or a lower case letter which follows a space:

var str = 'This Is A Cat';
if (str.match(/\b[a-z]/)) {
  console.log('Not Title Case');
}

var str2 = 'This is A Cat';
if (str2.match(/\b[a-z]/)) {
   console.log('Example 2 Is Not Title Case');
}

var str3 = 'this Is A Cat';
if (str3.match(/\b[a-z]/)) {
   console.log('Example 3 Is Not Title Case');
}
sideroxylon
  • 4,338
  • 1
  • 22
  • 40
1

What is wrong with my thinking?

You're finding a sequence of title-cased words, but that won't pick up cases where there are non-title-cased words.

You can test if the entire input is not title case with the simple regexp:

const tests = ['This Is A Cat', 'This is a cat', 'This Is A cat'];

// Is there any occurrence of a word break followed by lower case?
const re = /\b[a-z]/;

tests.forEach(test => console.log(test, "is not title case:", re.test(test)));

If you really want to check that the input is title case, then you'll need to match the string from beginning to end, as mentioned in a comment (i.e., "anchor" the regex):

const tests = ['This Is A Cat', 'This is a cat', 'This Is A cat'];

// Is the entire string a sequence of an upper case letter,
// followed by other letters and then spaces?
const re = /^\s*([A-Z]\w*\s*)*$/;

tests.forEach(test => console.log(test, "is title case:", re.test(test)));

What is title case?

Strictly speaking, however, articles, conjunctions, and prepositions are not upper-cased unless they start the title. Therefore, a better test would be:

const re = /^\s*[A-Z]\w*\s*(a|an|the|and|but|or|on|in|with|([A-Z]\w*)\s*)*$/;
0

My guessing is that you have forgotten to include the global match sign g at the end.

g finds all matches rather than stopping after the first match

Try to do it this way:

/(\b[A-Z][a-z]*\s*\b)+/g
Ibrahim
  • 6,006
  • 3
  • 39
  • 50
  • This will find all contiguous sequences of title-cased words, but how will it let you know that there were non-title-cased words? –  Nov 12 '16 at 05:49