test - regular expression validation javascript




如何訪問JavaScript正則表達式中的匹配組? (10)

我想使用正則表達式匹配字符串的一部分,然後訪問那個帶括號的子字符串:

var myString = "something format_abc"; // I want "abc"

var arr = /(?:^|\s)format_(.*?)(?:\s|$)/.exec(myString);

console.log(arr);     // Prints: [" format_abc", "abc"] .. so far so good.
console.log(arr[1]);  // Prints: undefined  (???)
console.log(arr[0]);  // Prints: format_undefined (!!!)

我究竟做錯了什麼?

我發現上面的正則表達式代碼沒有問題:我測試的實際字符串是這樣的:

"date format_%A"

報告“%A”未定義似乎是一個非常奇怪的行為,但它與這個問題沒有直接關係,所以我打開了一個新的, 為什麼匹配的子字符串在JavaScript中返回“undefined”?

問題在於console.log的參數類似於printf語句,並且由於我記錄的字符串( "%A" )有一個特殊的值,它試圖找到下一個參數的值。


在這個答案中使用的術語:

  • 匹配表示對您的字符串運行RegEx模式的結果,如下所示: someString.match(regexPattern)
  • 匹配模式表示輸入字符串的所有匹配部分,全部位於匹配數組內。 這些都是你的模式在輸入字符串中的所有實例。
  • 匹配的組指示要在RegEx模式中定義的所有要捕獲的組。 (括號內的模式,如下所示:/ /format_(.*?)/g (.*?) / /format_(.*?)/g ,其中(.*?)將是匹配的組)。這些模式位於匹配的模式中

描述

要訪問匹配的組 ,在每個匹配的模式中 ,需要一個函數或類似的東西來迭代匹配 。 有很多方法可以做到這一點,正如許多其他答案所示。 大多數其他答案使用while循環遍歷所有匹配的模式 ,但我認為我們都知道這種方法的潛在危險。 有必要與new RegExp()進行匹配,而不僅僅是只在評論中提到的模式本身。 這是因為.exec()方法的行為類似於生成器函數 - 每次匹配時都停止 ,但在下一次.exec()調用時保持.lastIndex繼續。

代碼示例

下面是一個函數searchString的例子,它返回一個所有匹配模式Array ,其中每個match是一個包含所有包含匹配組Array 。 我沒有使用while循環,而是使用Array.prototype.map()函數以及更Array.prototype.map()提供了示例 - 使用plain for -loop。

簡潔的版本(更少的代碼,更多的語法糖)

這些性能較差,因為它們基本上實現了forEach -loop而不是更快for -loop。

// Concise ES6/ES2015 syntax
const searchString = 
    (string, pattern) => 
        string
        .match(new RegExp(pattern.source, pattern.flags))
        .map(match => 
            new RegExp(pattern.source, pattern.flags)
            .exec(match));

// Or if you will, with ES5 syntax
function searchString(string, pattern) {
    return string
        .match(new RegExp(pattern.source, pattern.flags))
        .map(match =>
            new RegExp(pattern.source, pattern.flags)
            .exec(match));
}

let string = "something format_abc",
    pattern = /(?:^|\s)format_(.*?)(?:\s|$)/;

let result = searchString(string, pattern);
// [[" format_abc", "abc"], null]
// The trailing `null` disappears if you add the `global` flag

高性能版本(更多代碼,更少語法糖)

// Performant ES6/ES2015 syntax
const searchString = (string, pattern) => {
    let result = [];

    const matches = string.match(new RegExp(pattern.source, pattern.flags));

    for (let i = 0; i < matches.length; i++) {
        result.push(new RegExp(pattern.source, pattern.flags).exec(matches[i]));
    }

    return result;
};

// Same thing, but with ES5 syntax
function searchString(string, pattern) {
    var result = [];

    var matches = string.match(new RegExp(pattern.source, pattern.flags));

    for (var i = 0; i < matches.length; i++) {
        result.push(new RegExp(pattern.source, pattern.flags).exec(matches[i]));
    }

    return result;
}

let string = "something format_abc",
    pattern = /(?:^|\s)format_(.*?)(?:\s|$)/;

let result = searchString(string, pattern);
// [[" format_abc", "abc"], null]
// The trailing `null` disappears if you add the `global` flag

我還沒有將這些替代方案與前面在其他答案中提到的替代方案進行比較,但我懷疑這種方法的性能不如其他方式更高,且安全性更低。


以下是您可以用來獲取每個匹配的第n個捕獲組的方法:

function getMatches(string, regex, index) {
  index || (index = 1); // default to the first capturing group
  var matches = [];
  var match;
  while (match = regex.exec(string)) {
    matches.push(match[index]);
  }
  return matches;
}


// Example :
var myString = 'something format_abc something format_def something format_ghi';
var myRegEx = /(?:^|\s)format_(.*?)(?:\s|$)/g;

// Get an array containing the first capturing group for every match
var matches = getMatches(myString, myRegEx, 1);

// Log results
document.write(matches.length + ' matches found: ' + JSON.stringify(matches))
console.log(matches);


你的語法可能不是最好的。 FF / Gecko將RegExp定義為Function的擴展。
(FF2走到了typeof(/pattern/) == 'function'

這似乎是特定於FF - IE瀏覽器,Opera和Chrome都會拋出異常。

相反,使用前面提到的其他方法: RegExp#execString#match
他們提供了相同的結果:

var regex = /(?:^|\s)format_(.*?)(?:\s|$)/;
var input = "something format_abc";

regex(input);        //=> [" format_abc", "abc"]
regex.exec(input);   //=> [" format_abc", "abc"]
input.match(regex);  //=> [" format_abc", "abc"]

使用你的代碼:

console.log(arr[1]);  // prints: abc
console.log(arr[0]);  // prints:  format_abc

編輯:Safari 3,如果它很重要。


您可以像這樣訪問捕獲組:

var myString = "something format_abc";
var myRegexp = /(?:^|\s)format_(.*?)(?:\s|$)/g;
var match = myRegexp.exec(myString);
console.log(match[1]); // abc

如果有多個匹配,你可以迭代它們:

var myString = "something format_abc";
var myRegexp = /(?:^|\s)format_(.*?)(?:\s|$)/g;
match = myRegexp.exec(myString);
while (match != null) {
  // matched text: match[0]
  // match start: match.index
  // capturing group n: match[n]
  console.log(match[0])
  match = myRegexp.exec(myString);
}


最後但並非最不重要的是,我發現一行代碼對我很好(JS ES6):

var reg = /#([\S]+)/igm; //get hashtags
var string = 'mi alegría es total! ✌🙌\n#fiestasdefindeaño #PadreHijo #buenosmomentos #france #paris';

var matches = string.match(reg).map(e => e.replace(reg, '$1'));
console.log(matches);

這將返回: [fiestasdefindeaño, PadreHijo, buenosmomentos, france, paris]


看看第12課的這個鏈接

您可以使用特殊() (括號)對字符進行分組。 要捕獲圖像文件,請編寫表達式^(IMG(\d+))\.png$


關於上面的多匹配括號的例子,在我沒有得到我想要的東西之後,我在這裡尋找答案:

var matches = mystring.match(/(?:neededToMatchButNotWantedInResult)(matchWanted)/igm);

用上面的while和.push()函數調用稍微複雜的函數調用之後,我發現問題可以用mystring.replace()非常優雅地解決(代替不是重點,甚至沒有完成,CLEAN,第二個參數的內置遞歸函數調用選項是!):

var yourstring = 'something format_abc something format_def something format_ghi';

var matches = [];
yourstring.replace(/format_([^\s]+)/igm, function(m, p1){ matches.push(p1); } );

在此之後,我認為我永遠不會再使用.match()。


var myString = "something format_abc";
var arr = myString.match(/\bformat_(.*?)\b/);
console.log(arr[0] + " " + arr[1]);

\b並不完全一樣。 (它在--format_foo/上工作,但在format_a_b不起作用)但是我想顯示一個替代你的表達式,這很好。 當然, match電話是重要的。


/*Regex function for extracting object from "window.location.search" string.
 */

var search = "?a=3&b=4&c=7"; // Example search string

var getSearchObj = function (searchString) {

    var match, key, value, obj = {};
    var pattern = /(\w+)=(\w+)/g;
    var search = searchString.substr(1); // Remove '?'

    while (match = pattern.exec(search)) {
        obj[match[0].split('=')[0]] = match[0].split('=')[1];
    }

    return obj;

};

console.log(getSearchObj(search));






regex