簡體   English   中英

返回 Javascript 中正則表達式 match() 的位置?

[英]Return positions of a regex match() in Javascript?

有沒有辦法在 Javascript 中檢索正則表達式 match() 結果的字符串中的(起始)字符位置?

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

這是我想出的:

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

在現代瀏覽器中,您可以使用string.matchAll()完成此操作。

這種方法與RegExp.exec()的好處是它不依賴於有狀態的正則表達式,就像@Gumbo's answer中那樣。

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

來自developer.mozilla.org關於 String .match()方法的文檔:

返回的 Array 有一個額外的輸入屬性,其中包含已解析的原始字符串。 此外,它還有一個 index 屬性,表示字符串中匹配項的從零開始的索引

在處理非全局正則表達式(即,正則表達式上沒有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。

您可以使用String對象的search方法。 這僅適用於第一場比賽,但會按照您的描述進行。 例如:

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

這是我最近發現的一個很酷的功能,我在控制台上嘗試過,它似乎可以工作:

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

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

返回:“邊界 6 底部 13 左 18 半徑”

所以這似乎是你正在尋找的。

如果您的正則表達式與寬度 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 版本上使用 polyfill)是使用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字段。

有關瀏覽器支持和 polyfill 選項,請參閱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 的前瞻 - 它匹配l之前的 0 寬度字符串。所以它在第一次調用exec()時正確地轉到索引 2,然后停留在那里:

 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++ } }

此成員 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 ) );

這里得到線性項的位置索引。

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

如果您試圖獲得所有匹配的索引而不僅僅是第一個,這就是我想出的:

String.prototype.searchAll = function(regex) {
    return [...this.matchAll(regex)].map((match) => {return match.index});
}

// then use it
"1test2".searchAll(/\d/g) // [ 0, 5 ]

請注意,您必須使用 /g Global 標志才能使其工作

我很幸運地使用了這個基於matchAll的單行解決方案(我的用例需要一個字符串位置數組)

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

let matchIndices = Array.from(str.matchAll(regexp)).map(x => x.index);

console.log(matchIndices)

輸出:[3, 9]

 var str = 'my string here'; var index = str.match(/hre/).index; alert(index); // <- 10

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM