strugee
strugee

Reputation: 2800

How can I match a regex at the beginning _or_ end of the line?

I'm trying to create a JS regex that matches !next either at the beginning or end of the line.

Currently I'm using /(^!next|!next$)/i which works. However that's obviously kind of ugly to read and not DRY, so I'm looking to improve.

The closest I've come is this:

/(?=!next)[^$]/i

But that actually just matches everything (and it occurs to me now that I misremembered the way that ^ works inside character classes, so this solution is garbage anyway).

I've searched the web and SO, and I'm totally stumped.

Upvotes: 1

Views: 123

Answers (2)

user663031
user663031

Reputation:

You could try

function beginningOrEnd(input, search) {
  const pos = input.search(search);
  return pos === 0 || pos === input.length - search.length;
}

beginningOrEnd("hey, !help", "!help");

This uses search.length, so obviously search must be a string.

Or, you could construct the regexp yourself:

function beginningOrEnd(search) {
  return new RegExp(`^${search}|${search}\$`, "i");
}

beginningOrEnd("!help").test(input)

In the real world, you'd want to escape special regexp characters appropriately, of course.

Upvotes: 3

Sebastian Lenartowicz
Sebastian Lenartowicz

Reputation: 4854

Here's a fun one, using regex conditionals:

/(^)?!next(?(1)|$)/gm

Demo on Regex101

How it works is it captures the beginning-of-line anchor, and, if it is not present, matches the end-of-line anchor instead.

Personally, though, I'd still argue in favour of your solution over mine because it's more readable to someone who doesn't have an extremely thorough knowledge of regexes (and is more portable).

For added fun, here's another version (that's even uglier than your initial variant):

/!next(?:(?<=^.{5})|(?=$))/gm

Demo on Regex101

I'd still recommend sticking with the classic alternation, though.

And, finally, one that works in JS (no, really):

/(?:^|(?=.{5}$))!next/gm

Demo on Regex101

Upvotes: 4

Related Questions