Helpful Information
 
 
Category: Regex Programming
String Pattern

I need a regular expression to validate a string with the following requirements.

1. May contain Upper case, Lower case alphabets, Numbers and hyphens ( this works - "^[a-zA-Z0-9-]*$" )

Not sure how to handle the second requirement

2. The hyphen should not be at the beginning or end of the string. Also, no more than one hyphen consecutively.

Example Strings

B, 5, 12Ab3, Ba3, aBc-32, a1-b2-c3

2. The hyphen should not be at the beginning or end of the string. Also, no more than one hyphen consecutively.
Reword that and break it down a bit:
First character must be a letter or number
Last character must be a letter or number
Each hyphen must not have a hyphen on either side
So basically, letters and numbers are all treated the same, but hyphens have to be handled differently.
If you use assertions (lookbehinds and lookaheads) it's quite simple:

/^([a-zA-Z0-9]+|(?<!^|-)-(?!-|$))*$/
(?<!^|-) checks that the hyphen doesn't have a start-of-string or hyphen before,
(?!-|$) checks that it doesn't have a hyphen or end-of-string after.



Alternative ending:

function validate(string)
if (string has "--" OR string starts with "-" OR string ends with "-") return FALSE
return whether string passes /^[a-zA-Z0-9-]*$/
}
This may actually be faster, depending on the language.

...

Alternative ending:

function validate(string)
if (string has "--" OR string starts with "-" OR string ends with "-") return FALSE
return whether string passes /^[a-zA-Z0-9-]*$/
}
This may actually be faster, depending on the language.

@OP:
Nixie has a good point about the "Alternative ending". Although I don't think the speed will matter much unless you will be going to perform these kind of validations hundreds of times a second or if you're validating strings of thousands of characters long.
The real advantage of the "Alternative ending" is the fact that it's so much easier to read/understand and thus easier to maintain. The readability of code is also worth a lot IMO!

Also note that because of the *, that pattern will also match an empty string.

Thanks for your replies. But the regular expression suggested by requinix does not work. I am getting "Syntax error in Regular Expression" error. Can you please verify.

Thanks for your replies. But the regular expression suggested by requinix does not work. I am getting "Syntax error in Regular Expression" error. Can you please verify.

I works all right.
Can yo post how you used it and with what compiler/interpreter (what language did you use)?

I am testing on a HTML file in IE 7. Here is my HTML file.

<html>
<head>

<script type="text/javascript">
<!--
String.prototype.isText = function () {return /^([a-zA-Z0-9]+|(?<!^|-)-(?!-|$))*$/.test(this)}

function checkForText () {if (!this.value.isText()) {
alert ('Please, check the format for ' + this.previousSibling.data.replace(/\s+$/, '') + '.');
this.value = '';
this.focus();
}}

if (document.getElementById) onload = function () {
var e, i;
for (i = 0; e = document.forms[0].elements[i]; i++) {if (e.type == 'text') e.onchange = checkForText}
}
// -->
</script>
</head>

<body>

<form action="test.html">
<fieldset>
<legend>Regular Expression Test Form</legend>
<label>Test String1 <input name="test1" type="text"></label>
<button type="submit">Submit</button>
</fieldset>
</form>

</body>
</html>










privacy (GDPR)