JavaScript RegEx, совпадение нулевой длины с ИЛИ (может быть, смотреть вперед и назад)

У меня есть это регулярное выражение /\b\d\b/, чтобы просто сопоставить однозначное слово.

Теперь я хотел бы добавить символ подчеркивания в качестве альтернативы границе слова, поэтому я хотел бы также сопоставить цифру в "_1_", сохраняя подчеркивание как совпадение нулевой длины (как в \ b, поэтому я не Я не хочу, чтобы _ в матче).

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

Я попробовал несколько уловок с позитивным взглядом вперед / назад, взгляд вперед, кажется, работает, а взгляд назад - нет. Пытался выполнить необязательный просмотр вперед / назад и сделать что-то вроде _|\b, но я не смог найти для этого идеального решения.

Не очень разбираясь в продвинутых трюках с RegEx, я подумал, что спрошу, прежде чем делать это с двумя RegEx :)

Это должно быть выполнено на JavaScript.


person Samer Buna    schedule 03.07.2012    source источник


Ответы (2)


(?<=\b|_)\d(?=\b|_)

(?<=    # Positive look-behind
\b      # Word boundary
|       # Or
_       # Underscore
)       # End group
\d      # Digit
(?=     # Positive look-ahead
\b|_)   # Word boundary or underscore

Он будет соответствовать вашей единственной цифре и будет использовать либо границы слов (\b), либо подчеркивания (_) для сопоставления.

Он имеет нулевую длину, поэтому цифры, которым он соответствует, не группируются.

Поиграйте с регулярным выражением здесь.

person David B    schedule 03.07.2012
comment
Это по-прежнему будет включать символы подчеркивания в результате совпадения. Я хотел бы, чтобы подчеркивание было необязательным совпадением с нулевой длиной - person Samer Buna; 03.07.2012
comment
@SamerAbukhait Вы правы, я отредактировал его так, чтобы в нем не было подчеркивания. - person David B; 03.07.2012
comment
Это RegEx, который я на самом деле пробовал, но получаю неверную ошибку регулярного выражения. Я пробовал в Chrome, Node и даже Ruby 1.9. Прогнозирующая часть работает, но ретроспективная не работает. - person Samer Buna; 03.07.2012
comment
@SamerAbukhait Ага, провел небольшое исследование, и похоже, что JS не поддерживает ретроспективу. Я проведу небольшое исследование и посмотрю, можно ли это воспроизвести. - person David B; 03.07.2012
comment
Не могли бы вы отредактировать ответ и написать, что он еще не готов к использованию. Из v8project.blogspot.de/2016/02/regexp-lookbehind-assertions .html: You can already experiment with lookbehind assertions by running V8 version 4.9 or later with --harmony, or by enabling experimental JavaScript features (use about:flags) in Chrome from version 49 onwards. - person velop; 06.02.2017

Поскольку ретроспективы не работают в JS, вы можете сопоставить только свое основное регулярное выражение, в вашем случае \d, а затем вручную проверить границы.

const manualBoundaries = /\d/g
const matches = [];
while ((match = manualBoundaries.exec(str)) !== null) {
  const m = match[0]
  const i = match.index
  if ((i == 0 || str[i - 1].match(/(\W|_)/)) &&
      (i + m.length == str.length || str[i + m.length].match(/(\W|_)/)))
    matches.push(m)
}

Или, короче, на поддельную замену

const matches = [];
str.replace(manualBoundaries, (m, i) => {
    if ((i == 0 || str[i - 1].match(/(\W|_)/)) &&
        (i + m.length == str.length || str[i + m.length].match(/(\W|_)/)))
      matches.push(m);
});

Попробуйте здесь: https://jsfiddle.net/djjeck/mg2gzpf1/

person djjeck    schedule 28.10.2016