Как я могу совместить регулярное выражение в начале _OR_ конца строки?

Я пытаюсь создать регулярное выражение JS, которое соответствует !next либо в начале, либо в конце строки.

В настоящее время я использую /(^!next|!next$)/i, который работает. Однако, очевидно, что уродливо читать, а не СУХОЙ, поэтому я хочу улучшить.

Ближайший я пришел, это:

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

Но это на самом деле просто соответствует всем (и теперь мне приходит в голову, что я не помню, как ^ работает внутри классов символов, так что это решение - мусор в любом случае).

Я искал в Интернете и SO, и я полностью в тупике.

Ответ 1

Здесь весело, используя условные выражения:

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

Демо на Regex101

Как это работает, он фиксирует привязку начала строки, и, если он отсутствует, вместо этого привязывается к привязке конца строки.

Лично я все же спорю в пользу вашего решения над моим, потому что он более читабельен для человека, который не обладает чрезвычайно глубоким знанием регулярных выражений (и более переносимым).

Для дополнительной забавы, здесь другая версия (которая даже более уродливее, чем ваш первоначальный вариант):

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

Демо на Regex101

Я бы по-прежнему рекомендовал придерживаться классического чередования.

И, наконец, тот, который работает в JS (нет, действительно):

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

Демо на Regex101

Ответ 2

Вы можете попробовать

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

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

В этом случае используется search.length, поэтому search должен быть строкой.

Или вы можете сами создать регулярное выражение:

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

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

В реальном мире вы, конечно, должны избегать специальных символов регулярного выражения.