Question: I need a regex to meet the following requirements:

* Only letters, periods and whitespace are allowed.
* No white space at the beginning and at the end of the string.
* White space in the middle of the string is OK, but not two consecutive white spaces.

Matches: 

```
"Hello world."
"Hello World. This is ok."

```

Not Matches: 

```
" Hello World. "
"Hello world 123." 
"Hello  world."

```

This worked in my case 

```
<asp:RegularExpressionValidator ID="revDescription" runat="server" 
                                ControlToValidate="taDescription" Display="Dynamic" ErrorMessage="Invalid Description." 
                                Text="&nbsp" 
                                ValidationExpression="^(?i)(?![ ])(?!.*[ ]{2})(?!.*[ ]$)[A-Z. ]{8,20}$"></asp:RegularExpressionValidator>

```

Answer: 
Here's a solution in Python, using [anchors](http://www.regular-expressions.info/anchors.html) and [negative lookahead assertions](http://www.regular-expressions.info/lookaround.html) to make sure the whitespace rules are followed:

```
regex = re.compile(
    """^          # Start of string
    (?![ ])       # Assert no space at the start
    (?!.*[ ]{2})  # Assert no two spaces in the middle
    (?!.*[ ]$)    # Assert no space at the end
    [A-Z. ]{8,20} # Match 8-20 ASCII letters, dots or spaces
    $             # End of string""", 
    re.IGNORECASE | re.VERBOSE)

```
I'd suggest to check for the length outside of the regular expression, otherwise the expression might get too complicated.

Here's an example snippet in JavaScript:

```
if (str.length < 8 || str.length > 20)
  return false;
if (str.match(/(^\s|\s$|\s\s|[^A-Za-z.\s])/))
  return false;

```

The regular expression checks for a match of any of the forbidden patterns:

* `^\s` a whitespace at the beginning
* `\s$` a whitespace at the end
* `\s\s` two consecutive whitespace characters
* `[^A-Za-z.\s]` a character that is not a letter, period or whitespace

If you will allow only spaces (ASCII 32), not tabs or other whitespace characters, you can replace all `\s` by the literal space character.

Another solution would be a combination of a “positive” expression to check for the permitted characters and length and a “negative” one to rule out the rejected patterns:

```
return str.match(/[A-Za-z. ]){8,20}/) && !str.match(/(^ | $|  )/);

```

**Update**: If you need to put everything into a single expression, I'm afraid you have to leave out the check for consecutive spaces, because this restriction makes the language context-sensitive, hence it cannot be checked by a regular expression. What you can do is to check for a string that begins with a letter, followed by 6 to 18 letters, dots or spaces and ends with a letter:

```
[A-Z][A-Z. ]{6,18}[A-Z]

```