В чем разница между функцией exec () RegExp и функцией match () в String? - PullRequest
110 голосов
/ 09 февраля 2012

Если я запускаю это:

/([^\/]+)+/g.exec('/a/b/c/d');

Я получаю это:

["a", "a"]

Но если я запущу это:

'/a/b/c/d'.match(/([^\/]+)+/g);

Тогда я получу ожидаемый результат этого:

["a", "b", "c", "d"]

Какая разница?

Ответы [ 6 ]

104 голосов
/ 09 февраля 2012

exec с глобальным регулярным выражением предназначен для использования в цикле, так как он все равно будет извлекать все совпадающие подвыражения. Итак:

var re = /[^\/]+/g;
var match;

while (match = re.exec('/a/b/c/d')) {
    // match is now the next match, in array form.
}

// No more matches.

String.match делает это для вас и сбрасывает захваченные группы.

67 голосов
/ 09 февраля 2012

Одна картина лучше, вы знаете ...

re_once = /([a-z])([A-Z])/
re_glob = /([a-z])([A-Z])/g

st = "aAbBcC"

console.log("match once="+ st.match(re_once)+ "  match glob="+ st.match(re_glob))
console.log("exec once="+ re_once.exec(st) + "   exec glob="+ re_glob.exec(st))
console.log("exec once="+ re_once.exec(st) + "   exec glob="+ re_glob.exec(st))
console.log("exec once="+ re_once.exec(st) + "   exec glob="+ re_glob.exec(st))

видите разницу?

Примечание: Чтобы подчеркнуть, обратите внимание, что захваченные группы (например, a, A) возвращаются после сопоставленного шаблона (например, aA), это не просто сопоставленный шаблон.

28 голосов
/ 09 февраля 2012

/regex/.exec() возвращает только первое найденное совпадение, а "string".match() возвращает все из них, если вы используете флаг g в регулярном выражении.

Смотрите здесь: exec , match .

20 голосов
/ 15 октября 2015

Если ваше регулярное выражение является глобальным и вы захватываете, то вы должны использовать exec. Матч не вернет все ваши захваты.

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

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

Другое использование с Exec - получение индекса или позиции совпадения. Когда у вас есть переменная для вашего регулярного выражения, вы можете использовать .lastIndex и получить позицию соответствия. Объект регулярного выражения имеет .lastIndex, а объект регулярного выражения - это то, что вы делаете .exec. Сопоставление точек выполняется в строке, и вы не сможете затем выполнить регулярное выражение объекта dot lastIndex

Строка с функцией соответствия, которой передается регулярное выражение. И регулярное выражение, имеет функцию exec, и передается строка

Exec вы запускаете несколько раз. матч, который вы запускаете один раз

Хорошо использовать сопоставление, когда не выполняется захват, и при захвате можно использовать exec, который является более мощным, так как он полезен для получения захватов, но если вы использовали сопоставление при захвате, посмотрите, что он показывает захваты, когда регулярное выражение не является глобальным , но не показывает захваты, когда регулярное выражение является глобальным.

> "azb".match(/a(z)b/);
[ "azb", "z" ]

> "azb".match(/a(z)b/g);
[ "azb" ]
>

Другое дело, что если вы используете exec, обратите внимание, что он вызывается для регулярного выражения, то, если вы использовали переменную для регулярного выражения, у вас будет больше возможностей

Вы не получите совпадения, если не используете переменную для регулярного выражения, поэтому используйте переменную для регулярного выражения при использовании exec

> /./g.exec("abc")
[ "a" ]
> /./g.exec("abc")
[ "a" ]
> /./g.exec("abc")
[ "a" ]
>
> /[a-c]/g.exec("abc")
[ "a" ]
> /[a-c]/g.exec("abc")
[ "a" ]
>

> var r=/[a-c]/g
> r.exec("abc")
[ "a" ]
> r.exec("abc")
[ "b" ]
> r.exec("abc")
[ "c" ]
> r.exec("abc")
null
>

А с помощью exec вы можете получить «индекс» матча

> var r=/T/g
> r.exec("qTqqqTqqTq");
[ "T" ]
> r.lastIndex
2
> r.exec("qTqqqTqqTq");
[ "T" ]
> r.lastIndex
6
> r.exec("qTqqqTqqTq");
[ "T" ]
> r.lastIndex
9
> r.exec("qTqqqTqqTq");
null
> r.lastIndex
0
>

Так что если вы хотите индексировать или захватывать, то используйте exec (имейте в виду, что, как вы можете видеть, с «index», «index», который он дает, на самом деле является n-м вхождением, он рассчитывает с 1. Так что вы можете получить правильный индекс, вычитая 1. И, как вы можете видеть, он дает 0 - lastIndex = 0 - для не найден).

И если вы хотите растянуть совпадение, вы можете использовать его при захвате, но не тогда, когда регулярное выражение является глобальным, и когда вы делаете это для этого, тогда содержимое массива не все совпадения, но полное совпадение с последующими захватами.

5 голосов
/ 11 июня 2018

Функция .match () str.match(regexp) будет выполнять следующие действия:

  • , если равно совпадению, возвращается:
    • , если g флаг равен , используемому в регулярном выражении: он вернет все подстроки (игнорируя группы захвата)
    • , если флаг g не используется в регулярном выражении: он будет возвращать то же, что и regexp.exec(str)
  • , если есть нет совпадения, он вернет:
    • null

Примеры .match () с использованием флага g:

var str = "qqqABApppabacccaba";
var e1, e2, e3, e4, e5;
e1 = str.match(/nop/g); //null
e2 = str.match(/no(p)/g); //null
e3 = str.match(/aba/g); //["aba", "aba"]
e4 = str.match(/aba/gi); //["ABA", "aba", "aba"]
e5 = str.match(/(ab)a/g); //["aba", "aba"] ignoring capture groups as it is using the g flag

И .match () без флага g эквивалентно .exec () :

e1=JSON.stringify(str.match(/nop/))===JSON.stringify(/nop/.exec(str)); //true
//e2 ... e4 //true
e5=JSON.stringify(str.match(/(ab)a/))===JSON.stringify(/(ab)a/.exec(str)); //true

.exec() функция regexp.exec(str) сделает следующее:

  • , если равно совпадению, будет возвращено:
    • , если флаг g используется в регулярном выражении: оно будет возвращать (при каждом вызове) : [N_MatchedStr, N_Captured1, N_Captured2, ...] следующего N совпадения. Важно: оно не перейдет к следующему совпадению, если объект регулярного выражения не сохранен в переменной (это должен быть тот же объект)
    • , если флаг g равен не используется в регулярном выражении: он вернет то же самое, как если бы он имел флаг g и был вызван в первый раз и только один раз.
  • , если есть нет совпадение будет возвращено:
    • null

Пример .exec () (сохраненоregexp + с использованием флага g = он меняется при каждом вызове):

var str = "qqqABApppabacccaba";
var myexec, rgxp = /(ab)a/gi;

myexec = rgxp.exec(str);
console.log(myexec); //["ABA", "AB"]
myexec = rgxp.exec(str);
console.log(myexec); //["aba", "ab"]
myexec = rgxp.exec(str);
console.log(myexec); //["aba", "ab"]
myexec = rgxp.exec(str);
console.log(myexec); //null

//But in this case you should use a loop:
var mtch, myRe = /(ab)a/gi;
while(mtch = myRe.exec(str)){ //infinite looping with direct regexps: /(ab)a/gi.exec()
    console.log("elm: "+mtch[0]+" all: "+mtch+" indx: "+myRe.lastIndex);
    //1st iteration = elm: "ABA" all: ["ABA", "AB"] indx: 6
    //2nd iteration = elm: "aba" all: ["aba", "ab"] indx: 12
    //3rd iteration = elm: "aba" all: ["aba", "ab"] indx: 18
}

Примеры .exec () , когда не меняется с каждымЗвоните:

var str = "qqqABApppabacccaba", myexec, myexec2;

//doesn't go into the next one because no g flag
var rgxp = /(a)(ba)/;
myexec = rgxp.exec(str);
console.log(myexec); //["aba", "a", "ba"]
myexec = rgxp.exec(str);
console.log(myexec); //["aba", "a", "ba"]
//... ["aba", "a", "ba"]

//doesn't go into the next one because direct regexp
myexec2 = /(ab)a/gi.exec(str);
console.log(myexec2); //["ABA", "AB"]
myexec2 = /(ab)a/gi.exec(str);
console.log(myexec2); //["ABA", "AB"]
//... ["ABA", "AB"]
0 голосов
/ 11 ноября 2018

Иногда regex.exec () отнимает много времени больше, чем string.match ().

Стоит отметить, что если результат string.match () и regexТо же самоеПодход "new RegExp (). exec ()" следует использовать только тогда, когда вам нужно глобальное регулярное выражение (т. е. выполнять более одного раза).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...