Как получить все совпадения для регулярного выражения в JavaScript?



Я новичок в регулярных выражений. Я пытаюсь разобрать следующий вид строки:



[key:"val" key2:"val2"]



где есть произвольный ключ: пары " val " внутри. Я хочу получить имя ключа и значение.
Для тех, кому интересно, я пытаюсь разобрать формат базы данных из задач воина. Вот моя тестовая строка:



[description:"aoeu" uuid:"123sth"] что должно подчеркнуть, что все может быть в ключе или значении помимо пространства, никаких пробелов вокруг двоеточий, а значения всегда находятся в двойные кавычки. В узле, это мой вывод:



[deuteronomy][gatlin][~]$ node
> var re = /^[(?:(.+?):"(.+?)"s*)+]$/g
> re.exec('[description:"aoeu" uuid:"123sth"]');
[ '[description:"aoeu" uuid:"123sth"]',
'uuid',
'123sth',
index: 0,
input: '[description:"aoeu" uuid:"123sth"]' ]


но description:"aoeu" также соответствует этой схеме. Как я могу вернуть все спички?

729   13  

13 ответов:

продолжают называть re.exec(s) в цикле для получения всех совпадений:

var re = /\s*([^[:]+):\"([^"]+)"/g;
var s = '[description:"aoeu" uuid:"123sth"]';
var m;

do {
    m = re.exec(s);
    if (m) {
        console.log(m[1], m[2]);
    }
} while (m);

попробуйте это с помощью этого jsfiddle:http://jsfiddle.net/7yS2V/

чтобы перебрать все матчи, Вы можете использовать replace функция:

var re = /\s*([^[:]+):\"([^"]+)"/g;
var s = '[description:"aoeu" uuid:"123sth"]';

s.replace(re, function(match, g1, g2) { console.log(g1, g2); });

str.match(pattern) вернет все совпадения в виде массива. Я думаю, это самый простой способ.

например

"All of us except @Emran, @Raju and @Noman was there".match(/@\w*/g)
// Will return ["@Emran", "@Raju", "@Noman"]

Это решение

var s = '[description:"aoeu" uuid:"123sth"]';

var re = /\s*([^[:]+):\"([^"]+)"/g;
var m;
while (m = re.exec(s)) {
  console.log(m[1], m[2]);
}

это основано на ответе lawnsea, но короче.

обратите внимание, что флаг' g ' должен быть установлен для перемещения внутреннего указателя вперед по вызовам.

на основе функции Agus, но я предпочитаю возвращать только значения соответствия:

var bob = "> bob <";
function matchAll(str, regex) {
    var res = [];
    var m;
    if (regex.global) {
        while (m = regex.exec(str)) {
            res.push(m[1]);
        }
    } else {
        if (m = regex.exec(str)) {
            res.push(m[1]);
        }
    }
    return res;
}
var Amatch = matchAll(bob, /(&.*?;)/g);
console.log(Amatch);  // yeilds: [>, <]

вот моя функция, чтобы получить матчи:

function getAllMatches(regex, text) {
    if (regex.constructor !== RegExp) {
        throw new Error('not RegExp');
    }

    var res = [];
    var match = null;

    if (regex.global) {
        while (match = regex.exec(text)) {
            res.push(match);
        }
    }
    else {
        if (match = regex.exec(text)) {
            res.push(match);
        }
    }

    return res;
}

var regex = /abc|def|ghi/g;
var res = getAllMatches(regex, 'abcdefghi');

res.forEach(function (item) {
    console.log(item[0]);
});

для меня функция findall имеет важное значение, поэтому я упаковал ответ lawnsea в функцию для легкого копирования и вставки.

function findall(regex_pattern, string_)
    {
        var output_list = [];
        while (true) 
            {
                var a_match = regex_pattern.exec(string_);
                if (a_match) 
                    {
                        // get rid of the string copy
                        delete a_match.input;
                        // store the match data
                        output_list.push(a_match);
                    }
                else
                    {
                        break;
                    }
            } 
        return output_list;
    }

пример использования:

console.log(   findall(/blah/g,'blah1 blah2')   ) 

выходы:

[ [ 'blah', index: 0 ], [ 'blah', index: 6 ] ]

Iterables лучше:

const matches = (text, pattern) => ({
  [Symbol.iterator]: function * () {
    const clone = new RegExp(pattern.source, pattern.flags);
    let match = null;
    do {
      match = clone.exec(text);
      if (match) {
        yield match;
      }
    } while (match);
  }
});

использование в цикле:

for (const match of matches('abcdefabcdef', /ab/g)) {
  console.log(match);
}

или если вы хотите массив:

[ ...matches('abcdefabcdef', /ab/g) ]

OMG я не понимаю, что с 2011 года никто не прислал хороший ответ.

предположим, что ваша строка похожа на [key: "val" key2: "val2"], как указано выше @gatlin и вы хотите повторить все совпадения с помощью регулярного выражения : вы можете наслаждаться вторым параметром функции replace, который может быть функцией обратного вызова...а затем получить все аргументы, которые ваш regexp нашел. Далее пример, который вы можете играть в консоли:

var str = '[foo:"bar" thud:"grunt" bazola:"ztesch"]';
var regex = new RegExp('(\w+):"(\w+)"', 'ig');
var table = [];
str.replace(regex, function() {
    var matches = arguments;
    table.push(matches);
});
console.log(table);
//=> ["foo:"bar"", "foo", "bar", 1, .....

использовать это...

var all_matches = your_string.match(re);
console.log(all_matches)

он вернет массив всех совпадений...Это будет работать просто отлично.... Но помните, что он не будет принимать группы в account..It просто вернем полные матчи...

Я бы определенно рекомендовал использовать строку.функция match () и создание для нее соответствующего регулярного выражения. Мой пример - это список строк, который часто необходим при сканировании пользовательских входных данных для ключевых слов и фраз.

    // 1) Define keywords
    var keywords = ['apple', 'orange', 'banana'];

    // 2) Create regex, pass "i" for case-insensitive and "g" for global search
    regex = new RegExp("(" + keywords.join('|') + ")", "ig");
    => /(apple|orange|banana)/gi

    // 3) Match it against any string to get all matches 
    "Test string for ORANGE's or apples were mentioned".match(regex);
    => ["ORANGE", "apple"]

надеюсь, что это помогает!

Это на самом деле не поможет с вашей более сложной проблемой, но я публикую это в любом случае, потому что это простое решение для людей, которые не делают глобальный поиск, как вы.

я упростил регулярное выражение в ответе, чтобы быть более ясным (это не решение вашей точной проблемы).

var re = /^(.+?):"(.+)"$/
var regExResult = re.exec('description:"aoeu"');
var purifiedResult = purify_regex(regExResult);

// We only want the group matches in the array
function purify_regex(reResult){

  // Removes the Regex specific values and clones the array to prevent mutation
  let purifiedArray = [...reResult];

  // Removes the full match value at position 0
  purifiedArray.shift();

  // Returns a pure array without mutating the original regex result
  return purifiedArray;
}

// purifiedResult= ["description", "aoeu"]

это выглядит более подробным, чем это из-за комментариев, Вот как это выглядит без комментариев

var re = /^(.+?):"(.+)"$/
var regExResult = re.exec('description:"aoeu"');
var purifiedResult = purify_regex(regExResult);

function purify_regex(reResult){
  let purifiedArray = [...reResult];
  purifiedArray.shift();
  return purifiedArray;
}

обратите внимание, что любые группы, которые не совпадение будет указано в массиве как undefined значения.

Это решение использует оператор ES6 spread для очистки массива определенных значений регулярных выражений. Вам нужно будет запустить свой код через Бабель если вы хотите поддержку IE11.

вот мой ответ:

var str = '[me nombre es] : My name is. [Yo puedo] is the right word'; 

var reg = /\[(.*?)\]/g;

var a = str.match(reg);

a = a.toString().replace(/[\[\]]/g, "").split(','));

Comments

    Ничего не найдено.