Regex to match alphanumeric characters, underscore, periods and dash, allowing dot and dash only in the middle

delimited, php, preg-match, regex, validation

Solution

The answer would be

/^[a-zA-Z0-9_]+([-.][a-zA-Z0-9_]+)*$/

if only you allowed strings containing `.-` and `-.` NOT to match. Why would you allow them to match, anyway? But if you really need these strings to match too, a possible solution is

/^[a-zA-Z0-9_]+((\.(-\.)*-?|-(\.-)*\.?)[a-zA-Z0-9_]+)*$/

The single `.` or `-` of the first regex is replaced by a sequence of alternating `.` and `-`, starting with either `.` or `-`, optionally followed by `-.` or `.-` pairs respectively, optionally followed by a `-` or `.` respectively, to allow for an even number of alternating chars. This complexity is probably an overshoot, but appears to be needed by current specifications. If a max of 2 alternating `.` and `-` is required, the regex becomes

/^[a-zA-Z0-9_]+((\.-?|-\.?)[a-zA-Z0-9_]+)*$/

Test here or here

Problem

Presently, I am using this: ``` if (preg_match ('/^[a-zA-Z0-9_]+([a-zA-Z0-9_]*[.-]?[a-zA-Z0-9_]*)*[a-zA-Z0-9_]+$/', $product) ) { return true; } else { return false } ``` For example, I want to match: - `pro.duct-name_` - `_pro.duct.name` - `p.r.o.d_u_c_t.n-a-m-e` - `product.-name` - `____pro.-_-.d___uct.nam._-e` But I don't want to match: - `pro..ductname` - `.productname-` - `-productname.` - `-productname`

Original source