Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

regex - don't allow name to finish with hyphen

I'm trying to create a regex using javascript that will allow names like abc-def but will not allow abc- (hyphen is also the only nonalpha character allowed)

The name has to be a minimum of 2 characters. I started with ^[a-zA-Z-]{2,}$, but it's not good enough so I'm trying something like this ^([A-Za-z]{2,})+(-[A-Za-z]+)*$.

It can have more than one - in a name but it should never start or finish with -.

It's allowing names like xx-x but not names like x-x. I'd like to achieve that x-x is also accepted but not x-.

Thanks!

like image 619
ren Avatar asked Sep 02 '25 06:09

ren


2 Answers

Option 1

This option matches strings that begin and end with a letter and ensures two - are not consecutive so a string like a--a is invalid. To allow this case, see the Option 2.

^[a-z]+(?:-?[a-z]+)+$
  • ^ Assert position at the start of the line
  • [a-z]+ Match any lowercase ASCII letter one or more times (with i flag this also matches uppercase variants)
  • (?:-?[a-z]+)+ Match the following one or more times
    • -? Optionally match -
    • [a-z]+ Match any ASCII letter (with i flag)
  • $ Assert position at the end of the line

var a = [
  "aa","a-a","a-a-a","aa-aa-aa","aa-a", // valid
  "aa-a-","a","a-","-a","a--a" // invalid
]
var r = /^[a-z]+(?:-?[a-z]+)+$/i

a.forEach(function(s) {
  console.log(`${s}: ${r.test(s)}`)
})

Option 2

If you want to match strings like a--a then you can instead use the following regex:

^[a-z]+[a-z-]*[a-z]+$

var a = [
  "aa","a-a","a-a-a","aa-aa-aa","aa-a","a--a", // valid
  "aa-a-","a","a-","-a" // invalid
]
var r = /^[a-z]+[a-z-]*[a-z]+$/i

a.forEach(function(s) {
  console.log(`${s}: ${r.test(s)}`)
})
like image 141
ctwheels Avatar answered Sep 04 '25 21:09

ctwheels


You can use a negative lookahead:

/(?!.*-$)^[a-z][a-z-]+$/i

Regex101 Example

Breakdown:

// Negative lookahead so that it can't end with a -
(?!.*-$)

// The actual string must begin with a letter a-z
[a-z]

// Any following strings can be a-z or -, there must be at least 1 of these
[a-z-]+

let regex = /(?!.*-$)^[a-z][a-z-]+$/i;

let test = [
  'xx-x',
  'x-x',
  'x-x-x',
  'x-',
  'x-x-x-',
  '-x',
  'x'
];

test.forEach(string => {
  console.log(string, ':', regex.test(string));
});
like image 28
KevBot Avatar answered Sep 04 '25 21:09

KevBot