Группы захвата, не разделяющие группы [дубликат]

Все, что вам нужно, - перенаправить пользователя на какой-то URL выхода и вернуть на него ошибку 401 Unauthorized. На странице ошибок (которая должна быть доступна без базового auth) вам необходимо предоставить полную ссылку на вашу домашнюю страницу (включая схему и имя хоста).

Пример для Nginx:

location /logout {
    return 401;
}

error_page 401 /errors/401.html;

location /errors {
    auth_basic off;
    ssi        on;
    ssi_types  text/html;
    alias /home/user/errors;
}

Страница ошибки /home/user/errors/401.html:

<!DOCTYPE html>
<p>You're not authorised. <a href="<!--# echo var="scheme" -->://<!--# echo var="host" -->/">Login</a>.</p>
1068
задан Community 23 May 2017 в 11:55
поделиться

13 ответов

Доступ к группам захвата можно получить следующим образом:

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

1315
ответ дан Ruslan López 19 August 2018 в 08:11
поделиться
  • 1
    +1 Обратите внимание, что во втором примере вы должны использовать объект RegExp (не только & quot; / myregexp / & quot;), потому что он сохраняет значение lastIndex в объекте. Без использования объекта Regexp он будет бесконечно итерировать – ianaz 28 August 2012 в 13:06
  • 2
    @ianaz: Я не верю, что это правда? http://jsfiddle.net/weEg9/ похоже работает, по крайней мере, на Chrome. – spinningarrow 16 October 2012 в 08:26
  • 3
    Зачем делать выше, а не: var match = myString.match(myRegexp); // alert(match[1])? – JohnAllen 30 December 2013 в 19:39
  • 4
    Нет необходимости в явном «новом RegExp», однако бесконечный цикл будет происходить, если не указано значение / g – George Chen 6 June 2014 в 19:33
  • 5
    Другой способ не запускать в бесконечный цикл - это явно обновлять строку, например. string = string.substring(match.index + match[0].length) – Olga 11 February 2016 в 12:28

Что касается приведенных выше примеров круглых скобок с несколькими совпадениями, я искал ответ здесь, не получив того, что хотел:

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 () для чего-то снова.

21
ответ дан Alexz 19 August 2018 в 08:11
поделиться

Нет необходимости ссылаться на метод exec! Вы можете использовать метод «match» непосредственно в строке. Просто не забудьте скобки.

var str = "This is cool";
var matches = str.match(/(This is)( cool)$/);
console.log( JSON.stringify(matches) ); // will print ["This is cool","This is"," cool"] or something like that...

Позиция 0 имеет строку со всеми результатами. Позиция 1 имеет первое совпадение, представленное круглыми скобками, а позиция 2 имеет второе совпадение, выделенное в ваших круглых скобках. Вложенные круглые скобки сложны, поэтому будьте осторожны!

5
ответ дан Andre Carneiro 19 August 2018 в 08:11
поделиться

Вот метод, который вы можете использовать для получения группы захвата n th для каждого совпадения:

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

154
ответ дан Blowsie 19 August 2018 в 08:11
поделиться
  • 1
    Это гораздо лучший ответ другим, потому что он правильно показывает итерацию во всех матчах, а не только одну. – Rob Evans 11 May 2013 в 13:08
  • 2
    mnn является правильным. Это приведет к бесконечному циклу, если флаг «g» отсутствует. Будьте очень осторожны с этой функцией. – Druska 4 September 2013 в 19:45
  • 3
    Я улучшил это, чтобы сделать его похожим на re.findall () python. Он группирует все совпадения в массив массивов. Он также фиксирует проблему глобального цикла модификатора. jsfiddle.net/ravishi/MbwpV – ravishi 21 November 2013 в 22:00
  • 4
    @MichaelMikowski теперь вы только что скрыли свой бесконечный цикл, но ваш код будет работать медленно. Я бы сказал, что лучше иметь перерыв кода в плохой способ, чтобы вы его поймали в разработке. Включение некоторых прерываний с максимальными итерациями bs является неаккуратным. Скрывать проблемы, а не устранять их первопричину, не ответ. – wallacer 29 October 2014 в 19:34
  • 5
    @MichaelMikowski, который не имеет значительного замедления, когда вы не достигли предела выполнения. Когда вы находитесь, это заметно намного медленнее. Я не говорю, что ваш код не работает, я говорю, что на практике я думаю, что это принесет больше вреда, чем пользы. Люди, работающие в среде разработчиков, будут видеть, что код работает нормально под нагрузкой, несмотря на то, что 10 000 ненужных исполнений некоторых фрагментов кода. Затем они выталкивают его в производственную среду и задаются вопросом, почему их приложение падает под нагрузкой. По моему опыту, лучше, если все будет выглядеть очевидным образом, а раньше в цикле разработки. – wallacer 13 November 2014 в 00:44

Ваш код работает для меня (FF3 на Mac), даже если я согласен с PhiLo , что регулярное выражение должно быть:

/\bformat_(.*?)\b/

(Но, конечно, я Я не уверен, потому что я не знаю контекста регулярного выражения.)

1
ответ дан Community 19 August 2018 в 08:11
поделиться
  • 1
    это список, разделенный пробелами, поэтому я решил, что \ s будет в порядке. странно, что этот код не работал для меня (FF3 Vista) – nickf 11 January 2009 в 13:04
  • 2
    Да, действительно странно. Вы пробовали его самостоятельно в консоли Firebug? В противном случае я имею в виду. – PEZ 11 January 2009 в 13:21

Терминология, используемая в этом ответе:

  • Соответствие указывает результат запуска вашего шаблона RegEx против вашей строки следующим образом: someString.match(regexPattern).
  • Совпадающие шаблоны показывают все согласованные части входной строки, которые все находятся внутри массива совпадений. Это все экземпляры вашего шаблона внутри входной строки.
  • Совпадающие группы указывают на то, что все группы пойманы, определенные в шаблоне RegEx. (Шаблоны в круглых скобках, например: /format_(.*?)/g, где (.*?) будет подобранной группой.) Они находятся в согласованных шаблонах.

Описание

To получить доступ к сопоставленным группам , в каждом из сопоставленных шаблонов вам нужна функция или что-то похожее на итерацию по совпадению . Есть несколько способов сделать это, как показывают многие другие ответы. Большинство других ответов используют цикл while для повторения всех сопоставленных шаблонов , но я думаю, что мы все знаем потенциальные опасности с этим подходом. Необходимо сопоставлять с new RegExp(), а не только с самим шаблоном, который упоминается только в комментарии. Это связано с тем, что метод .exec() ведет себя аналогично функции генератора - , он останавливается каждый раз, когда имеется совпадение , но сохраняет его .lastIndex, чтобы продолжить оттуда следующий .exec() вызов.

Примеры кода

Ниже приведен пример функции searchString, которая возвращает Array всех совпадающих паттернов , где каждый match является Array со всеми содержащими сопоставленными группами . Вместо использования цикла while я предоставил примеры, используя как функцию Array.prototype.map(), так и более эффективный способ - используя простой 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

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

7
ответ дан Daniel Hallgren 19 August 2018 в 08:11
поделиться

Используя ваш код:

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

Редактирование: Safari 3, если это имеет значение.

4
ответ дан eyelidlessness 19 August 2018 в 08:11
поделиться

Ваш синтаксис, вероятно, не лучший. FF / Gecko определяет RegExp как расширение функции. (FF2 дошел до typeof(/pattern/) == 'function')

Кажется, это специфично для FF-IE, Opera и Chrome, все исключения для него исключают.

Вместо этого используйте любой метод ранее упомянутые другими: RegExp#exec или String#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"]
15
ответ дан Jonathan Lonowski 19 August 2018 в 08:11
поделиться

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

\b не совсем то же самое. (Он работает на --format_foo/, но не работает на format_a_b). Но я хотел показать альтернативу вашему выражению, что хорошо. Конечно, вызов match - важная вещь.

48
ответ дан Michael 19 August 2018 в 08:11
поделиться
  • 1
    Это точно наоборот. '\ b' ограничивает слова. word = '\ w' = [a-zA-Z0-9_]. & Quot; format_a_b & Quot; это слово. – B.F. 22 April 2015 в 21:09
  • 2
    @ B.F.Hostestly, я добавил, что «не работает на format_a_b». как после мысли 6 лет назад, и я не помню, что я имел в виду там ... :-) Я полагаю, это означало «не работает, чтобы захватить a только», т.е. первая алфавитная часть после format_. – PhiLho 23 April 2015 в 07:41
  • 3
    Я хотел сказать, что \ b (- format_foo /} \ b не возвращает & quot; - format_foo / & quot ;, потому что & quot; - & quot; и & quot; / & quot; не имеют \ слова символов. Но \ b (format_a_b) \ b do return & quot; format_a_b ". Правильно? Я ссылаюсь на ваш текстовый оператор в круглых скобках. (Не проголосовало!) – B.F. 23 April 2015 в 10:43

Один вкладыш, который практичен, только если у вас есть одна пара скобок:

while ( ( match = myRegex.exec( myStr ) ) && matches.push( match[1] ) ) {};
5
ответ дан Nabil Kadimi 19 August 2018 в 08:11
поделиться

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 = 'Rs.200 is Debited to A/c ...2031 on 02-12-14 20:05:49 (Clear Bal Rs.66248.77) AT ATM. TollFree 1800223344 18001024455 (6am-10pm)';
var myRegEx = /clear bal.+?(\d+\.?\d{2})/gi;

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

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

2
ответ дан Nisse Engström 19 August 2018 в 08:11
поделиться
/*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));
0
ответ дан Pawel Kwiecien 19 August 2018 в 08:11
поделиться

И последнее, но не менее важное: я обнаружил, что один строчный код, который отлично работал для меня (JS ES6):

var reg = /#([\S]+)/igm; //get hashtags
var string = 'mi alegría es total! ✌                  
9
ответ дан Sebastien H. 19 August 2018 в 08:11
поделиться
  • 1
    это хорошо работает, за исключением случаев, когда совпадение не может найти ничего, чем карта не работает. – MBehtemam 25 November 2017 в 12:23
Другие вопросы по тегам:

Похожие вопросы: