Odpowiedzi:
exec
zwraca obiekt z index
właściwością:
var match = /bar/.exec("foobar");
if (match) {
console.log("match found at " + match.index);
}
Oraz dla wielu dopasowań:
var re = /bar/g,
str = "foobarfoobar";
while ((match = re.exec(str)) != null) {
console.log("match found at " + match.index);
}
re
zmiennej jako zmiennej i dodanie g
modyfikatora są kluczowe! W przeciwnym razie otrzymasz niekończącą się pętlę.
undefined
. jsfiddle.net/6uwn1vof/2, który nie jest przykładem podobnym do wyszukiwania, jak twój.
g
flagę i zadziała. Ponieważ match
jest funkcją ciągu, a nie wyrażenia regularnego, nie może być stanową exec
, więc traktuje ją tylko jako exec
(tj. Ma właściwość index), jeśli nie szukasz globalnego dopasowania ... ponieważ wtedy stan nie ma znaczenia .
Oto, co wymyśliłem:
// 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);
}
match.index + match[0].length
działa również dla pozycji końcowej.
match.index + match[0].length - 1
?
.slice()
i .substring()
. Koniec obejmujący byłby o 1 mniej, jak mówisz. (Uważaj, że dołączenie zwykle oznacza indeks ostatniego znaku wewnątrz dopasowania, chyba że jest to pusty mecz, w którym jest 1 przed dopasowaniem i może znajdować -1
się całkowicie poza ciągiem dla pustego dopasowania na początku ...)
Z dokumentacji developer.mozilla.org na temat .match()
metody String :
Zwrócona Array ma dodatkową właściwość wejściową, która zawiera oryginalny ciąg, który został przeanalizowany. Ponadto ma właściwość index, która reprezentuje liczony od zera indeks dopasowania w ciągu .
Kiedy mamy do czynienia z nieglobalnym wyrażeniem regularnym (tj. Brakiem g
flagi w Twoim wyrażeniu regularnym), wartość zwracana przez .match()
ma index
właściwość… wszystko, co musisz zrobić, to uzyskać do niego dostęp.
var index = str.match(/regex/).index;
Oto przykład pokazujący, że również działa:
var str = 'my string here';
var index = str.match(/here/).index;
alert(index); // <- 10
Z powodzeniem przetestowałem to aż do IE5.
Możesz użyć search
metody String
obiektu. To zadziała tylko dla pierwszego dopasowania, ale poza tym zrobi to, co opisujesz. Na przykład:
"How are you?".search(/are/);
// 4
Oto fajna funkcja, którą niedawno odkryłem, wypróbowałem to na konsoli i wydaje się, że działa:
var text = "border-bottom-left-radius";
var newText = text.replace(/-/g,function(match, index){
return " " + index + " ";
});
Który zwrócił: „border 6 bottom 13 left 18 radius”
Więc wydaje się, że to jest to, czego szukasz.
arguments
. Nie „drugi argument”. Argumentami funkcji są "pełne dopasowanie, grupa1, grupa2, ...., indeks dopasowania, pełny ciąg dopasowany do"
W nowoczesnych przeglądarkach można to osiągnąć za pomocą string.matchAll () .
Zaletą tego podejścia RegExp.exec()
jest to, że nie polega ono na tym, że wyrażenie regularne jest stanowe, jak w odpowiedzi @ Gumbo .
let regexp = /bar/g;
let str = 'foobarfoobar';
let matches = [...str.matchAll(regexp)];
matches.forEach((match) => {
console.log("match found at " + match.index);
});
Ten element członkowski fn zwraca tablicę pozycji opartych na 0, jeśli takie istnieją, słowa wejściowego wewnątrz obiektu 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 ;
}
Spróbuj teraz
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 ) );
Możesz także wprowadzić wyrażenia regularne:
var _second = "z^2+2z-1" ;
console.log( _second.matching_positions( "[0-9]\z+", 0, 0, 0 ) );
Tutaj otrzymujemy indeks pozycji członu liniowego.
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
tutaj po prostu znajduje następne wystąpienie tekstu przechwyconego przez dopasowanie, które niekoniecznie jest zgodne. JS regex obsługuje warunki w tekście poza przechwytywaniem z wyprzedzeniem. Na przykład searchIndex("foobarfoobaz", "foo(?=baz)", true)
powinien dawać [6]
, a nie [0]
.
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
lub
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