Просмотр вперед. Регулярные выражения

Внутри круглых скобок могут быть расположены следующие конструкции:

  • (?=...) — положительный просмотр вперед. Выведем все слова, после которых расположена запятая:
let p = /\w+(?=[,])/g;
let str = 'text1, text2, text3 text4';
console.log( str.match(p) ); // [ 'text1', 'text2' ]
  • (?!...) — отрицательный просмотр вперед. Выведем все слова, после которых нет запятой:
let p = /[a-z]+[0-9](?![,])/g;
let str = 'text1, text2, text3 text4';
console.log( str.match(p) ); // [ 'text3', 'text4' ]

Рассмотрим небольшой пример. Предположим необходимо получить все слова, расположенные после тире, причем перед тире и после слов должны следовать пробельные символы:

const process = require('process');
let p = /\s\-([a-z0-9]+)\s/g;
let str = '-word1 -word2 -word3 -word4 -word5';
let arr;
while ( (arr = p.exec(str)) ) {
   process.stdout.write(arr[1] + ' ');
}
// word2 word4

Как видно из примера, мы получили только два слова вместо пяти. Первое и последнее слово не попали в результат, так как расположены в начале и в конце строки. Чтобы эти слова попали в результат, необходимо добавить альтернативные выборы: (^|\s) — для начала строки и (\s|$) — для конца строки. Чтобы найденные выражения внутри круглых скобок не попали в результат, следует добавить символы ?: после открывающей скобки:

const process = require('process');
let p = /(?:^|\s)\-([a-z0-9]+)(?:\s|$)/g;
let str = '-word1 -word2 -word3 -word4 -word5';
let arr;
while ( (arr = p.exec(str)) ) {
   process.stdout.write(arr[1] + ' ');
}
// word1 word3 word5

Первое и последнее слово успешно попали в результат. Почему же слова word2 и word4 не попали в список совпадений? Ведь и перед тире есть пробел, и после слова есть пробел. Чтобы понять причину рассмотрим поиск по шагам. Первое слово успешно попадает в результат, так как перед тире расположено начало строки, и после слова есть пробел. После поиска указатель перемещается, и строка для дальнейшего поиска примет следующий вид:

"-word1 <Указатель>-word2 -word3 -word4 -word5"

Обратите внимание на то, что перед фрагментом -word2 больше нет пробела, и тире не расположено в начале строки. Поэтому следующим совпадением станет слово word3, и указатель снова будет перемещен:

"-word1 -word2 -word3 <Указатель>-word4 -word5"

Опять перед фрагментом -word4 нет пробела, и тире не расположено в начале строки. Поэтому следующим совпадением станет слово word5, и поиск будет завершен. Таким образом, слова word2 и word4 не попадают в результат, поскольку пробел до фрагмента уже был использован в предыдущем поиске. Чтобы этого избежать, следует воспользоваться положительным просмотром вперед (?=...):

const process = require('process');
let p = /(?:^|\s)\-([a-z0-9]+)(?=\s|$)/g;
let str = '-word1 -word2 -word3 -word4 -word5';
let arr;
while ( (arr = p.exec(str)) ) {
   process.stdout.write(arr[1] + ' ');
}
// word1 word2 word3 word4 word5

В этом примере мы заменили фрагмент (?:\s|$) на (?=\s|$). Поэтому все слова успешно попали в список совпадений.

Учебник по Node.js и JavaScript
Учебник по JavaScript (Node.js) в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов