197

Javascriptの正規表現match()の結果の文字列内の(開始)文字位置を取得する方法はありますか?

4

11 に答える 11

274

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

于 2010-02-19T10:49:16.187 に答える
71

これが私が思いついたものです:

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

于 2010-02-19T11:38:26.793 に答える
20

最近のブラウザでは、string.matchAll()を使用してこれを実行できます。

このアプローチの利点は、 @ Gumboの回答のRegExp.exec()ように、正規表現がステートフルであることに依存しないことです。

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

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

于 2020-07-09T21:50:25.247 に答える
18

Stringメソッドに関するdeveloper.mozilla.orgドキュメントから:.match()

返される配列には、解析された元の文字列を含む追加の入力プロパティがあります。さらに、文字列内の一致のゼロベースのインデックスを表すインデックスプロパティがあります

非グローバル正規表現を処理する場合(つまり、正規g表現にフラグがない場合)、によって返される値に.match()indexプロパティがあります...必要なのはそれにアクセスすることだけです。

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

これも機能していることを示す例です。

var str = 'my string here';

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

console.log(index); // <- 10

私はこれをIE5までさかのぼって正常にテストしました。

于 2016-03-29T22:44:39.803 に答える
9

searchオブジェクトのメソッドを使用できStringます。これは最初の試合でのみ機能しますが、それ以外の場合はあなたが説明したことを行います。例えば:

"How are you?".search(/are/);
// 4
于 2010-02-19T10:51:37.760 に答える
6

これが最近発見したクールな機能です。コンソールでこれを試しましたが、機能しているようです。

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

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

返されたもの:「境界線6下13左18半径」

だから、これはあなたが探しているもののようです。

于 2016-10-30T13:39:25.277 に答える
2

正規表現が幅0に一致する場合、以前の回答(に基づくexec)は機能しないようです。たとえば(注:/\b/gすべての単語の境界を検出する必要がある正規表現です):

var re = /\b/g,
    str = "hello world";
var guard = 10;
while ((match = re.exec(str)) != null) {
    console.log("match found at " + match.index);
    if (guard-- < 0) {
      console.error("Infinite loop detected")
      break;
    }
}

正規表現を少なくとも1文字一致させることでこれを修正することができますが、これは理想からはほど遠いです(つまり、文字列の最後に手動でインデックスを追加する必要があります)

var re = /\b./g,
    str = "hello world";
var guard = 10;
while ((match = re.exec(str)) != null) {
    console.log("match found at " + match.index);
    if (guard-- < 0) {
      console.error("Infinite loop detected")
      break;
    }
}

より良い解決策(新しいブラウザでのみ機能する/古い/ IEバージョンではポリフィルが必要)は、String.prototype.matchAll()を使用することです。

var re = /\b/g,
    str = "hello world";
console.log(Array.from(str.matchAll(re)).map(match => match.index))

説明:

String.prototype.matchAll()は、グローバル正規表現(gグローバルフラグが設定された正規表現)を想定しています。次に、イテレータを返します。ループオーバーしmap()てイテレータを作成するには、配列に変換する必要があります(これがまさにそのArray.from()機能です)。の結果と同様に、結果のRegExp.prototype.exec()要素.indexには仕様に従ったフィールドがあります。

ブラウザのサポートとポリフィルオプションについては、 String.prototype.matchAll()およびArray.from() MDNページを参照してください。


編集:すべてのブラウザでサポートされているソリューションを探すためにもう少し深く掘り下げる

の問題RegExp.prototype.exec()は、正規表現のポインタが更新lastIndexされ、次回は以前に見つかったから検索を開始することlastIndexです。

var re = /l/g,
str = "hello world";
console.log(re.lastIndex)
re.exec(str)
console.log(re.lastIndex)
re.exec(str)
console.log(re.lastIndex)
re.exec(str)
console.log(re.lastIndex)

これは、正規表現の一致に実際に幅がある限り、うまく機能します。0幅の正規表現を使用する場合、このポインターは増加しないため、無限ループが発生します(注:/(?=l)/gはlの先読みです。これは、前の0幅の文字列と一致しますl。したがって、最初のインデックス2に正しく移動します。の呼び出しexec()、そしてそこにとどまります:

var re = /(?=l)/g,
str = "hello world";
console.log(re.lastIndex)
re.exec(str)
console.log(re.lastIndex)
re.exec(str)
console.log(re.lastIndex)
re.exec(str)
console.log(re.lastIndex)

したがって、解決策(matchAll()ほど良くはありませんが、すべてのブラウザーで機能するはずです)は、一致幅が0の場合にlastIndexを手動で増やすことです(さまざまな方法でチェックできます)。

var re = /\b/g,
    str = "hello world";
while ((match = re.exec(str)) != null) {
    console.log("match found at " + match.index);

    // alternative: if (match.index == re.lastIndex) {
    if (match[0].length == 0) {
      // we need to increase lastIndex -- this location was already matched,
      // we don't want to match it again (and get into an infinite loop)
      re.lastIndex++
    }
}

于 2021-06-12T10:22:39.550 に答える
1

このメンバーfnは、Stringオブジェクト内の入力ワードの0ベースの位置の配列を返します(存在する場合)。

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

ここで、線形項の位置インデックスを取得します。

于 2015-09-25T16:40:28.673 に答える
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));
于 2016-06-27T11:17:13.017 に答える
-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
于 2019-12-12T18:40:43.580 に答える
-1

var str = 'my string here';

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

alert(index); // <- 10

于 2020-12-22T12:53:03.527 に答える