Вернуть позиции регулярного выражения match () в Javascript?


154

Есть ли способ получить (начальные) позиции символов внутри строки результатов регулярного выражения match () в Javascript?

Ответы:


225

execвозвращает объект со indexсвойством:

var match = /bar/.exec("foobar");
if (match) {
    console.log("match found at " + match.index);
}

И для нескольких матчей:

var re = /bar/g,
    str = "foobarfoobar";
while ((match = re.exec(str)) != null) {
    console.log("match found at " + match.index);
}


5
Спасибо за вашу помощь! Можете ли вы также сказать мне, как я могу найти индексы нескольких совпадений?
Stagas

9
Примечание: использование в reкачестве переменной и добавление gмодификатора имеют решающее значение! В противном случае вы получите бесконечный цикл.
Ориадам

1
@ OnurYıldırım - вот jsfiddle из этого работает ... Я проверил все это до IE5 ... прекрасно работает: jsfiddle.net/6uwn1vof
Джимбо Джонни

1
@JimboJonny, я хорошо узнал что-то новое. Мой тестовый случай возвращается undefined. jsfiddle.net/6uwn1vof/2, который не похож на ваш пример поиска.
Онур Йылдырым

1
@ OnurYıldırım - Уберите gфлаг, и он будет работать. Поскольку matchэто функция строки, а не регулярное выражение, она не может быть похожей на состояние exec, поэтому она обрабатывает ее как exec(т.е. имеет свойство index), если вы не ищете глобального соответствия ... потому что тогда состояние не имеет значения ,
Джимбо Джонни

60

Вот что я придумал:

// Finds starting and ending positions of quoted text
// in double or single quotes with escape char support like \" \'
var str = "this is a \"quoted\" string as you can 'read'";

var patt = /'((?:\\.|[^'])*)'|"((?:\\.|[^"])*)"/igm;

while (match = patt.exec(str)) {
  console.log(match.index + ' ' + patt.lastIndex);
}


18
match.index + match[0].lengthтакже работает для конечной позиции.
Бени Чернявский-Паскин


1
@ BeniCherniavsky-Paskin, не будет ли конечная позиция match.index + match[0].length - 1?
Дэвид

1
@ Давид, я имел в виду исключительную конечную позицию, как, например, .slice()и .substring(). Инклюзивный конец будет на 1 меньше, как вы говорите. (Будьте осторожны, инклюзивный обычно означает индекс последнего символа в матче, если только это не пустое совпадение, где он равен 1 перед матчем и может находиться -1вне строки целиком для пустого совпадения в начале ...)
Бени Чернявский-Паскин

16

Из документации developer.mozilla.org о .match()методе String :

Возвращаемый массив имеет дополнительное входное свойство, которое содержит исходную строку, которая была проанализирована. Кроме того, у него есть свойство index, которое представляет нулевой индекс совпадения в строке .

При работе с неглобальным регулярным выражением (т. Е. Без gфлага на вашем регулярном выражении) возвращаемое значение .match()имеет indexсвойство ... все, что вам нужно сделать - это получить к нему доступ.

var index = str.match(/regex/).index;

Вот пример, показывающий, как это работает:

var str = 'my string here';

var index = str.match(/here/).index;

alert(index); // <- 10

Я успешно проверил это вплоть до IE5.


6

Вы можете использовать searchметод Stringобъекта. Это будет работать только для первого матча, но в противном случае будет делать то, что вы описываете. Например:

"How are you?".search(/are/);
// 4

6

Вот интересная особенность, которую я обнаружил недавно, я попробовал это на консоли, и она, кажется, работает:

var text = "border-bottom-left-radius";

var newText = text.replace(/-/g,function(match, index){
    return " " + index + " ";
});

Что вернуло: "граница 6, нижний 13, левый 18 радиус"

Так что это, кажется, то, что вы ищете.


6
просто имейте в виду, что функции замены также добавляют группы захвата, поэтому обратите внимание, что это всегда вторая позиция в функции замены, argumentsкоторая является позицией. Не «второй аргумент». Аргументы функции: «полное совпадение, group1, group2, ...., индекс совпадения, сопоставление полной строки»
Mike 'Pomax' Kamermans

2

В современных браузерах вы можете сделать это с помощью string.matchAll () .

Преимущество этого подхода по сравнению с тем RegExp.exec(), что он не основан на регулярном выражении, как в ответе @ Gumbo .

let regexp = /bar/g;
let str = 'foobarfoobar';

let matches = [...str.matchAll(regexp)];
matches.forEach((match) => {
    console.log("match found at " + match.index);
});


1

Этот член fn возвращает массив позиций на основе 0, если таковые имеются, входного слова внутри объекта String

String.prototype.matching_positions = function( _word, _case_sensitive, _whole_words, _multiline )
{
   /*besides '_word' param, others are flags (0|1)*/
   var _match_pattern = "g"+(_case_sensitive?"i":"")+(_multiline?"m":"") ;
   var _bound = _whole_words ? "\\b" : "" ;
   var _re = new RegExp( _bound+_word+_bound, _match_pattern );
   var _pos = [], _chunk, _index = 0 ;

   while( true )
   {
      _chunk = _re.exec( this ) ;
      if ( _chunk == null ) break ;
      _pos.push( _chunk['index'] ) ;
      _re.lastIndex = _chunk['index']+1 ;
   }

   return _pos ;
}

Сейчас попробуй

var _sentence = "What do doers want ? What do doers need ?" ;
var _word = "do" ;
console.log( _sentence.matching_positions( _word, 1, 0, 0 ) );
console.log( _sentence.matching_positions( _word, 1, 1, 0 ) );

Вы также можете ввести регулярные выражения:

var _second = "z^2+2z-1" ;
console.log( _second.matching_positions( "[0-9]\z+", 0, 0, 0 ) );

Здесь можно получить индекс положения линейного члена.


1
var str = "The rain in SPAIN stays mainly in the plain";

function searchIndex(str, searchValue, isCaseSensitive) {
  var modifiers = isCaseSensitive ? 'gi' : 'g';
  var regExpValue = new RegExp(searchValue, modifiers);
  var matches = [];
  var startIndex = 0;
  var arr = str.match(regExpValue);

  [].forEach.call(arr, function(element) {
    startIndex = str.indexOf(element, startIndex);
    matches.push(startIndex++);
  });

  return matches;
}

console.log(searchIndex(str, 'ain', true));

Это неверно str.indexOfздесь просто находит следующее вхождение текста, захваченного совпадением, которое не обязательно совпадает. JS регулярное выражение поддерживает условия для текста за пределами захвата с предвидением. Например searchIndex("foobarfoobaz", "foo(?=baz)", true)должен дать [6], а не [0].
Ракслице

почему `[] .forEach.call (arr, function (element)` почему нет arr.forEach или arr.map
Ankit Kumar

-1
function trimRegex(str, regex){
    return str.substr(str.match(regex).index).split('').reverse().join('').substr(str.match(regex).index).split('').reverse().join('');
}

let test = '||ab||cd||';
trimRegex(test, /[^|]/);
console.log(test); //output: ab||cd

или

function trimChar(str, trim, req){
    let regex = new RegExp('[^'+trim+']');
    return str.substr(str.match(regex).index).split('').reverse().join('').substr(str.match(regex).index).split('').reverse().join('');
}

let test = '||ab||cd||';
trimChar(test, '|');
console.log(test); //output: ab||cd
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.