designermonkey
designermonkey

Reputation: 1108

How do i limit this match to one character

I have a regular expression

(?<=\w)([A-Z]|_|\s)

That matches against the following correctly

ModelName  (matches N)
modelName  (matches N)
Model Name (matches space)
model name (matches space)
model_name (matches underscore)

but the following is incorrect

Model_Name (matches underscore and N)

In the latter, I need to only match the space, but have the same regexp matches on all the previous results.

I'm a little rusty, so does anyone know how to best achieve this?

My context is as follows:

/**
 * Converts 'ModelName', 'modelName' and 'model_name' to 'model-name'
 * @param  string $word
 * @return string
 */
public static function hyphenate($word)
{
    return strtolower(str_replace([' ', '_'], '', preg_replace('!(?<=\\w)([A-Z]|_|\\s)!', '-$1', $word)));
}

The last failing match will make this function return model--name.

Would it be easier to just do another str_replace('--', '', $word) before returning?

Upvotes: 2

Views: 55

Answers (1)

Robin
Robin

Reputation: 9644

To do it all in one step you can use

preg_replace('/(?<=[a-zA-Z])(?:([A-Z])|[_\h])/', '-\1', $string);

See demo here.

The idea is to capture the uppercase letter in first capturing group, which will then be empty if you match a _ or \h (horizontal whitespace).

Your issue was that \w stands for [a-zA-Z_], so the look behind matched _ as well.

Upvotes: 6

Related Questions