Соответствие Vs exec в JavaScript
Мне нужно некоторое уточнение для соответствия Vs exec в JavaScript; здесь кто-то говорит, что
"exec с глобальным регулярным выражением предназначен для использования в цикле", но прежде всего, как вы видите в моем примере, это не так; в моем примере exec с глобальным регулярным выражением возвращает все совпадения в массиве! Во-вторых, они говорят, что для String.match он возвращает все совпадения без необходимости прокрутки! Но опять же, что не происходит в моем примере, и он просто возвращает строку ввода? Я неправильно понял/сделал что-то не так?
var myString = "[22].[44].[33].";
var myRegexp = /.*\[(\d*)*\].*\[(\d*)*\].*\[(\d*)*\].*/g;
var execResult = myRegexp.exec(myString);
console.log(execResult.length);
console.log(execResult[1]);// returns 22 and execResult has all of my matches from index 1 to the length of array
var matchResult = myString.match(myRegexp);
console.log(matchResult.length);
console.log(matchResult);// returns just myString which is "[22].[44].[33]."! Why is that?
Ответы
Ответ 1
-
string.match
находит первое совпадение и возвращает его с фактическим совпадением, индекс, по которому был найден текст, и фактический ввод, когда глобальный флаг не используется.
-
string.match
просто возвращает все совпадения, когда используется глобальный флаг.
var myString = "[22].[44].[33].";
console.log(myString.match(/\d+/));
# [ '22', index: 1, input: '[22].[44].[33].' ]
console.log(myString.match(/\d+/g));
# [ '22', '44', '33' ]
Основное различие между string.match
и regex.exec
заключается в том, что объект regex
будет обновлен в текущем совпадении с вызовом regex.exec
. Например,
var myString = "[22].[44].[33].", myRegexp = /\d+/g, result;
while (result = myRegexp.exec(myString)) {
console.log(result, myRegexp.lastIndex);
}
вернет
[ '22', index: 1, input: '[22].[44].[33].' ] 3
[ '44', index: 6, input: '[22].[44].[33].' ] 8
[ '33', index: 11, input: '[22].[44].[33].' ] 13
Как вы можете видеть, свойство lastIndex
обновляется всякий раз, когда встречается совпадение. Итак, помните о двух вещах, когда вы используете exec
или , вы столкнетесь с бесконечным циклом.
-
Если вы не используете параметр g
, вы всегда получите первое совпадение, если оно есть, иначе null
. Итак, следующее будет работать в бесконечном цикле.
var myString = "[22].[44].[33].", myRegexp = /\d+/, result;
while (result = myRegexp.exec(myString)) {
console.log(result, myRegexp.lastIndex);
}
-
Не забудьте использовать тот же объект регулярного выражения с последующими вызовами. Поскольку объект regex обновляется каждый раз, и если вы передаете новый объект, снова программа будет запущена в бесконечный цикл.
var myString = "[22].[44].[33].", result;
while (result = /\d+/g.exec(myString)) {
console.log(result);
}
Ответ 2
String.prototype.match()
и RegExp.prototype.exec()
одинаковы как при поиске нескольких вхождений, так и при их возврате в массив. И все же метод exec возвращает массив более подробной информации. Например, в отличие от совпадения, он также может найти несколько вхождений групп захвата. Так что если у вас есть группы захвата, exec необходим. При работе с exec следует помнить одну вещь, которую вы не должны вызывать из буквального регулярного выражения. Сначала присвойте свое регулярное выражение переменной и используйте его для вызова вашего метода exec. Другое дело, что в то время как сопоставление будет приводить к множеству вхождений в массиве элементов за один раз, с exec вы должны выполнять итерацию для каждого регистрируемого вхождения.
Вызов матча довольно прост. Так как это метод прототипа строки, вы просто связываете его со строкой и предоставляете регулярное выражение в качестве аргумента метода match подобно; "test".match(/es /) Буквальное представление регулярного выражения можно использовать без проблем.
Вызов exec более сложен. Как я упоминал ранее, лучше иметь регулярное выражение для чего-то ранее. Хорошо, давайте посмотрим на пример
var text = '["job name 1","nat 1"],["job name 2","nat 2"],["job name 3","nat 3"]',
reg = /([^"]+)","([^"]+)/g,
tm = [],
te = [];
tm = text.match(reg); // tm has result of match
while(te[te.length]=reg.exec(text)); // te has result of exec + an extra null item at the end
te.length--; // te normalized.
document.write("<pre>" + JSON.stringify(tm,null,2) + "</pre>\n");
document.write("<pre>" + JSON.stringify(te,null,2) + "</pre>\n");