Restituisci le posizioni di una partita regex () in Javascript?


154

C'è un modo per recuperare le posizioni dei caratteri (iniziali) all'interno di una stringa dei risultati di una corrispondenza regex () in Javascript?

Risposte:


225

execrestituisce un oggetto con una indexproprietà:

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

E per più partite:

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


5
Grazie per l'aiuto! Puoi dirmi anche come posso trovare gli indici di più corrispondenze?
stagas,

9
Nota: l'uso di recome variabile e l'aggiunta del gmodificatore sono entrambi fondamentali! Altrimenti otterrai un ciclo infinito.
Oriadam,

1
@ OnurYıldırım - eccone un jsfiddle funzionante ... L'ho provato fino a IE5 ... funziona alla grande: jsfiddle.net/6uwn1vof
Jimbo Jonny

1
@JimboJonny, hm beh ho imparato qualcosa di nuovo. Il mio caso di prova ritorna undefined. jsfiddle.net/6uwn1vof/2 che non è un esempio di ricerca come il tuo.
Onur Yıldırım

1
@ OnurYıldırım - Rimuovi la gbandiera e funzionerà. Poiché matchè una funzione della stringa, non della regex di cui non può essere stateful exec, quindi la tratta solo come exec(cioè ha una proprietà index) se non stai cercando una corrispondenza globale ... perché quindi lo statefulness non ha importanza .
Jimbo Jonny,

60

Ecco cosa mi è venuto in mente:

// 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].lengthfunziona anche per la posizione finale.
Beni Cherniavsky-Paskin,

davvero bello - confronto qui
Louis Maddox il

1
@ BeniCherniavsky-Paskin, la posizione finale non sarebbe match.index + match[0].length - 1?
David,

1
@ David, intendevo la posizione finale esclusiva, come ad esempio presa da .slice()e .substring(). La fine inclusiva sarebbe 1 in meno come dici tu. (Fai attenzione che inclusivo di solito significhi un indice dell'ultimo carattere all'interno della partita, a meno che non sia una partita vuota in cui è 1 prima della partita e potrebbe essere -1al di fuori della stringa per una partita vuota all'inizio ...)
Beni Cherniavsky-Paskin,

16

Dai documenti developer.mozilla.org sul .match()metodo String :

L'array restituito ha una proprietà di input aggiuntiva, che contiene la stringa originale analizzata. Inoltre, ha una proprietà index, che rappresenta l'indice in base zero della corrispondenza nella stringa .

Quando si ha a che fare con una regex non globale (ovvero, nessuna gbandiera sul proprio regex), il valore restituito da .match()ha una indexproprietà ... tutto quello che devi fare è accedervi.

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

Ecco un esempio che mostra che funziona anche:

var str = 'my string here';

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

alert(index); // <- 10

Ho testato con successo tutto questo fino a IE5.


6

È possibile utilizzare il searchmetodo Stringdell'oggetto. Funzionerà solo per la prima partita, ma altrimenti farà ciò che descrivi. Per esempio:

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

6

Ecco una bella funzionalità che ho scoperto di recente, l'ho provato sulla console e sembra funzionare:

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

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

Che ha restituito: "bordo 6 inferiore 13 sinistra 18 raggio"

Quindi questo sembra essere quello che stai cercando.


6
fai attenzione che le funzioni di sostituzione aggiungono anche i gruppi di acquisizione, quindi tieni presente che è sempre la penultima voce della funzione di sostituzione a argumentsessere la posizione. Non "il secondo argomento". Gli argomenti della funzione sono "corrispondenza completa, gruppo1, gruppo2, ...., indice di corrispondenza, stringa completa confrontata con"
Mike 'Pomax' Kamermans,

2

Nei browser moderni, puoi farlo con string.matchAll () .

Il vantaggio di questo approccio vs RegExp.exec()è che non si basa sul fatto che la regex sia stateful, come nella risposta di @ Gumbo .

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

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


1

Questo membro fn restituisce un array di posizioni basate su 0, se presenti, della parola di input all'interno dell'oggetto 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 ;
}

Adesso prova

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 ) );

Puoi anche inserire espressioni regolari:

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

Qui si ottiene l'indice di posizione del termine lineare.


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));

Questo non è corretto str.indexOfqui trova solo la prossima occorrenza del testo catturato dalla corrispondenza, che non è necessariamente la corrispondenza. JS regex supporta le condizioni sul testo al di fuori dell'acquisizione con lookahead. Ad esempio searchIndex("foobarfoobaz", "foo(?=baz)", true)dovrebbe dare [6], no [0].
rakslice,

why `[] .forEach.call (arr, function (element)` why not arr.forEach or 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

o

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.