Есть ли способ добиться эквивалента негативного взгляда в регулярных выражениях javascript? Мне нужно сопоставить строку, которая не начинается с определенного набора символов.
Кажется, я не могу найти регулярное выражение, которое делает это без сбоев, если совпадающая часть найдена в начале строки. Негативные взгляды, кажется, единственный ответ, но у javascript его нет.
РЕДАКТИРОВАТЬ: Это регулярное выражение, которое я хотел бы работать, но это не так:
(?<!([abcdefg]))m
Таким образом, это будет соответствовать «м» в «Джим» или «м», но не «джем»
javascript
regex
negative-lookbehind
Эндрю Энсли
источник
источник
(?:[^abcdefg]|^)(m)
? Как в"mango".match(/(?:[^abcdefg]|^)(m)/)[1]
Ответы:
Взгляд за утверждениями был принят в спецификации ECMAScript в 2018 году.
Положительный взгляд за использование:
Отрицательный взгляд за использование:
Поддержка платформы:
источник
Начиная с 2018 года утверждения типа «Сзади» являются частью спецификации языка ECMAScript .
Ответ до 2018 года
Поскольку Javascript поддерживает негативную перспективу , один из способов сделать это:
перевернуть строку ввода
совпадать с обратным регулярным выражением
отменить и переформатировать матчи
Пример 1:
После вопроса Эндрю Энсли:
Выходы:
Пример 2:
После комментария @neaumusic (соответствует,
max-height
но неline-height
соответствует токенуheight
):Выходы:
источник
max-height
но нет,line-height
и я только хочу, чтобы матч былheight
''(?!\()
заменит апострофы''(''test'''''''test
с другого конца, оставив,(''test'NNNtest
а не(''testNNN'test
.Предположим, вы хотите найти все, что
int
не предшествуетunsigned
:С поддержкой негативного поиска:
Без поддержки негативных взглядов:
По сути, идея состоит в том, чтобы захватить n предшествующих символов и исключить совпадение с отрицательным прогнозом, но также сопоставить случаи, когда нет предшествующих n символов. (где n - длина оглядки назад).
Итак, регулярное выражение в вопросе:
будет переводить на:
Возможно, вам придется поиграть с группами захвата, чтобы найти точное место строки, которая вас интересует, или вы хотите заменить определенную часть чем-то другим.
источник
"So it would match the 'm' in 'jim' or 'm', but not 'jam'".replace(/(j(?!([abcdefg])).|^)m/g, "$1[MATCH]")
возвращается"So it would match the 'm' in 'ji[MATCH]' or 'm', but not 'jam'"
Это довольно просто, и это работает!Стратегия Миходжи работает для вашего конкретного случая, но не в целом:
Вот пример, где цель состоит в том, чтобы соответствовать двойному l, но не если ему предшествует «ba». Обратите внимание на слово «balll» - истинный взгляд сзади должен был подавить первые 2 л, но соответствовать 2-й паре. Но, сопоставляя первые 2 л и затем игнорируя это совпадение как ложное срабатывание, механизм регулярных выражений исходит из конца этого совпадения и игнорирует все символы в ложном положительном результате.
источник
использование
источник
newString
всегда будет равнымstring
. Почему так много голосов?"Jim Jam Momm m".replace(/([abcdefg])?m/g, function($0, $1){ return $1 ? $0 : '[match]'; });
. Это должно вернутьсяJi[match] Jam Mo[match][match] [match]
. Но также обратите внимание, что, как упоминал Джейсон ниже, он может потерпеть неудачу в некоторых случаях.Вы можете определить группу без захвата, отрицая ваш набор символов:
... который будет соответствовать каждому
m
НЕ предшествующему любому из этих букв.источник
(?:[^a-g]|^)m
. См. Regex101.com/r/jL1iW6/2 для запуска примера.Вот как я достиг
str.split(/(?<!^)@/)
для Node.js 8 (который не поддерживает lookbehind):Работает? Да (Юникод не проверен). Неприятно? Да.
источник
следуя идее Mijoja и опираясь на проблемы, выявленные JasonS, у меня появилась эта идея; Я проверил немного, но я не уверен в себе, так что проверка кем-то более опытным, чем я в JS Regex будет здорово :)
мой личный вывод:
принцип состоит в том, чтобы вызывать
checker
в каждой точке строки между любыми двумя символами, когда эта позиция является отправной точкой:--- любая подстрока с размером нежелательного (здесь
'ba'
, таким образом..
) (если этот размер известен; в противном случае, возможно, это будет сложнее сделать)--- --- или меньше этого, если это начало строки:
^.?
и, после этого,
--- что нужно искать (здесь
'll'
).При каждом вызове
checker
будет проверяться, не является ли ранее значениеll
не тем, что мы не хотим (!== 'ba'
); если это так, мы вызываем другую функцию, и именно эта (doer
) будет вносить изменения в str, если целью является эта или, в более общем смысле, то будет вводить данные, необходимые для обработки вручную. Результаты сканированияstr
.здесь мы меняем строку, поэтому нам нужно было отслеживать разницу в длине, чтобы компенсировать местоположения, заданные
replace
, наstr
которые все рассчитано , что само по себе никогда не меняется.поскольку примитивные строки являются неизменяемыми, мы могли бы использовать переменную
str
для хранения результата всей операции, но я подумал, что пример, уже усложненный заменами, будет более понятным с другой переменной (str_done
).Я предполагаю, что с точки зрения производительности это должно быть довольно резким: все эти бессмысленные замены '' в '',
this str.length-1
времена, плюс здесь ручная замена делающим, что означает много нарезки ... вероятно, в этом конкретном вышеупомянутом случае, который мог бы быть сгруппированы, разрезая строку только один раз на части вокруг того места, где мы хотим вставить[match]
и.join()
объединяя ее с[match]
собой.Другое дело, что я не знаю, как он справится с более сложными случаями, то есть со сложными значениями для фальшивого вида сзади ... длина, пожалуй, самая проблематичная для получения данных.
и, в
checker
случае множественных возможностей нежелательных значений для $ behind, нам нужно будет проверить его с еще одним регулярным выражением (checker
лучше кэшировать (создавать) снаружи ), чтобы избежать создания того же самого объекта регулярного выражения. при каждом вызовеchecker
) знать, действительно ли это то, чего мы стремимся избежать.надеюсь, я был чист; если не стесняйтесь, я постараюсь лучше. :)
источник
Используя ваш случай, если вы хотите заменить
m
что-то, например, преобразовать его в верхний регистрM
, вы можете отменить набор в группе захвата.сопоставить
([^a-g])m
, заменить на$1M
([^a-g])
будет соответствовать любому символу not (^
) вa-g
диапазоне и сохранит его в первой группе захвата, чтобы вы могли получить к нему доступ с помощью$1
.Таким образом , мы находим
im
вjim
и заменить его ,iM
что приводит кjiM
.источник
Как уже упоминалось ранее, JavaScript позволяет теперь смотреть назад. В старых браузерах вам все еще нужен обходной путь.
Бьюсь об заклад, в моей голове нет способа найти регулярное выражение без взгляда назад, которое точно дает результат. Все, что вы можете сделать, это работать с группами. Предположим, у вас есть регулярное выражение
(?<!Before)Wanted
, гдеWanted
это регулярное выражение, которое вы хотите сопоставить, иBefore
это регулярное выражение, которое отсчитывает то, что не должно предшествовать совпадению. Лучшее, что вы можете сделать, это отменить регулярное выражениеBefore
и использовать регулярное выражениеNotBefore(Wanted)
. Желаемый результат - первая группа$1
.В вашем случае
Before=[abcdefg]
это легко отрицатьNotBefore=[^abcdefg]
. Так что регулярное выражение будет[^abcdefg](m)
. Если вам нужна позицияWanted
, вы также должны сгруппироватьNotBefore
, так что желаемый результат - вторая группа.Если совпадения
Before
шаблона имеют фиксированную длинуn
, то есть если шаблон не содержит повторяющихся токенов, вы можете избежать отрицанияBefore
шаблона и использовать регулярное выражение(?!Before).{n}(Wanted)
, но все равно придется использовать первую группу или использовать регулярное выражение(?!Before)(.{n})(Wanted)
и использовать второе группа. В этом примере шаблон наBefore
самом деле имеет фиксированную длину, а именно 1, поэтому используйте регулярное выражение(?![abcdefg]).(m)
или(?![abcdefg])(.)(m)
. Если вас интересуют все совпадения, добавьтеg
флаг, посмотрите мой фрагмент кода:источник
Это эффективно делает это
Пример поиска и замены
Обратите внимание, что отрицательная строка поиска должна быть длиной 1 символ, чтобы это работало.
источник
"m".match(/[^a-g]m/)
да,null
тоже. Я тоже хочу "м" в этом случае./(?![abcdefg])[^abcdefg]m/gi
да, это трюкисточник
(?![abcdefg])
полностью избыточна, поскольку[^abcdefg]
уже выполняет свою работу, чтобы предотвратить сопоставление этих символов.