Node JS - Extract Regex Именованные группы захвата Ключевые пары значений [dубликат]

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

Это. Держи это так, как ты.

144
задан mmierins 20 March 2011 в 09:02
поделиться

8 ответов

ECMAScript 2018 вводит группы захвата в регулярные выражения JavaScript.

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

Есть только два «структурных» преимущества названных групп захвата, о которых я могу думать:

  1. В некоторых вариантах регулярных выражений (.NET и JGSoft, насколько я знаю) , вы можете использовать одно и то же имя для разных групп в вашем регулярном выражении ( см. здесь для примера, где это имеет значение ). Но большинство разновидностей регулярных выражений в любом случае не поддерживают эту функциональность.
  2. Если вам нужно сослаться на нумерованные группы захвата в ситуации, когда они окружены цифрами, вы можете получить проблему. Предположим, вы хотите добавить нуль к цифре и, следовательно, хотите заменить (\ d) на $ 10 . В JavaScript это будет работать (до тех пор, пока в вашем регулярном выражении будет менее 10 групп захвата), но Perl подумает, что вы ищете номер обратной ссылки 10 вместо номера 1 ​​, а затем 0 . В Perl вы можете использовать $ {1} 0 в этом случае.

Кроме этого, группы захвата называются «синтаксическим сахаром». Это помогает использовать группы захвата только тогда, когда они вам действительно понадобятся, и использовать во всех других случаях не захватывающие группы (?: ...) .

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

Библиотека XRegExp Стив Левитана решает эти проблемы.

65
ответ дан Tim Pietzcker 16 August 2018 в 03:44
поделиться
  • 1
    Многие варианты позволяют использовать одно и то же имя группы захвата несколько раз в регулярном выражении. Но только .NET и Perl 5.10+ делают это особенно полезным, сохраняя значение, захваченное последней группой имени, которое участвовало в матче. – slevithan 1 June 2012 в 04:36
  • 2
    Огромное преимущество: вы можете просто изменить свой RegExp, не сопоставляя число-переменные. Нехватывающие группы решают эту проблему, за исключением одного случая: что, если порядок групп изменяется? Кроме того, он хочет добавить эти дополнительные символы в другие группы ... – Alba Mendez 9 November 2012 в 17:45
  • 3
    Так называемый синтаксический сахар делает помогает подсластить читаемость кода! – Mrchief 31 July 2013 в 19:32
  • 4
    Он будет заполнять непревзойденные с неопределенным. Некоторые языки не заставят вас использовать именованные. – jgmjgm 10 September 2015 в 01:37
  • 5
    Я думаю, что есть еще одна причина для названных групп захвата, которые действительно ценны. Например, если вы хотите использовать регулярное выражение для синтаксического анализа даты из строки, вы можете написать гибкую функцию, которая принимает значение и регулярное выражение. Пока регулярное выражение назвало захваты за год, месяц и дату, вы можете запустить массив регулярных выражений с минимальным кодом. – Dewey Vozel 18 January 2016 в 21:33

Вы можете использовать XRegExp , расширенную, расширяемую кросс-браузерную реализацию регулярных выражений, включая поддержку дополнительного синтаксиса, флагов и методов:

  • Добавляет новый синтаксис регулярных выражений и замены текста, включая всестороннюю поддержку с именем capture .
  • Добавляет два новых флага регулярных выражений: s , чтобы совпадение точек со всеми символами ( aka dotall или singleline mode) и x , для свободного пробега и комментариев (aka extended mode).
  • Предоставляет набор функций и методов, которые делают сложный регулярный просмотр обработкой ветерок .
  • Автоматически исправляет наиболее часто встречающиеся непоследовательности кросс-браузера в поведении и синтаксисе regex.
  • Позволяет вам легко создавать и использовать плагины, которые добавляют новый синтаксис и флаги к регулярному языку выражения XRegExp.
60
ответ дан Barett 16 August 2018 в 03:44
поделиться

В ES6 вы можете использовать деструктурирование массива, чтобы поймать ваши группы:

  let text = '27 months ';  пусть regex = / (\ d +) \ s * (days? | months? | years?) /;  let [, count, unit] = text.match (regex) ||  [];  // count === '27' // unit === 'months'  

Обратите внимание:

  • первая запятая в последней пусть пропускает первое значение результирующего массива, который представляет собой целую согласованную строку
  • the || [] после .match () предотвратит ошибку разрушения, если совпадений нет (поскольку .match () вернет null ])
38
ответ дан bfred.it 16 August 2018 в 03:44
поделиться
  • 1
    Первая запятая состоит в том, что первый элемент массива, возвращаемый совпадением, является входным выражением, правильно? – Emilio Grisolía 31 July 2016 в 01:04
  • 2
    String.prototype.match возвращает массив с: всей совпадающей строкой в ​​позиции 0, а затем с любыми группами после нее. Первая запятая говорит «пропустить элемент в положении 0», – bfred.it 31 July 2016 в 06:34
  • 3
    Мой любимый ответ здесь для тех, у кого есть транспиляция или цели ES6 +. Это не обязательно предотвращает ошибки несоответствия, а также именованные индексы, если, например, повторно используется регулярное выражение, но я думаю, что краткость здесь легко компенсирует это. Я выбрал RegExp.prototype.exec над String.prototype.match в местах, где строка может быть null или undefined . – Mike Hill 31 July 2017 в 15:29

Существует библиотека node.js, названная named-regexp , которую вы можете использовать в проектах node.js (в браузере путем упаковки библиотеки с помощью браузера или других сценариев упаковки). Тем не менее, библиотека не может использоваться с регулярными выражениями, которые содержат неименованные группы захвата.

Если вы считаете открывающие скобки для захвата в своем регулярном выражении, вы можете создать сопоставление между именованными группами захвата и нумерованными группами захвата в вашем регулярном выражении и может свободно смешиваться и сочетаться. Вам просто нужно удалить имена групп, прежде чем использовать регулярное выражение. Я написал три функции, которые демонстрируют это. См. Этот пояс: https://gist.github.com/gbirke/2cc2370135b665eee3ef

5
ответ дан chiborg 16 August 2018 в 03:44
поделиться
  • 1
    Это удивительно легкий, я попробую – bfred.it 1 August 2016 в 05:58
  • 2
    Работает ли она с вложенными именованными группами внутри регулярных групп в сложных регулярных выражениях? – ElSajko 14 October 2016 в 22:18
  • 3
    Это не идеально. Ошибка, когда: getMap (& quot; ((a | b (: & lt; foo & gt; c))) "); foo должен быть третьей, а не второй. /((a|b(c)))/g.exec("bc"); [& quot; bc "," bc "," bc "," c "], – ElSajko 14 October 2016 в 22:27

Именованные группы захвата могут быстро перейти на JavaScript. Предложение для него уже на этапе 3.

Группе захвата может быть присвоено имя с использованием синтаксиса (? ...) для любого имени идентификатора. Регулярное выражение для даты тогда может быть записано как / (? \ D {4}) - (? \ D {2}) - (? \ D {2}) / u. Каждое имя должно быть уникальным и следовать грамматике имени ECMAScript IdentifierName.

Доступ к именованным группам можно получить из свойств свойства групп результата регулярного выражения. Также создаются нумерованные ссылки на группы, как и для неименованных групп. Например:

  let re = / (& lt; year & gt; \ d {4}) - (& lt; month & gt; \ d {2}) - (& lt; day & gt; \  д {2}) / U;  let result = re.exec ('2015-01-02');  // result.groups.year === '2015';  // result.groups.month === '01';  // result.groups.day === '02';  // result [0] === '2015-01-02';  // result [1] === '2015';  // result [2] === '01';  // result [3] === '02';   
3
ответ дан Forivin 16 August 2018 в 03:44
поделиться

Хотя вы не можете сделать это с помощью ванильного JavaScript, возможно, вы можете использовать некоторую функцию Array.prototype , такую ​​как Array.prototype.reduce , чтобы превратить индексированные совпадения в именованные с помощью некоторой магии .

Очевидно, что следующее решение будет иметь следующие соответствия:

// @text Содержит текст для соответствия // @regex Объект регулярного выражения (fe /.+/) // @matchNames Массив литералов, где каждый элемент // является именем каждой групповой функции namedRegexMatch (text, regex, matchNames) {var matches = regex.exec (текст); return match.reduce (function (result, match, index) {if (index & gt; 0) // Эта подстановка требуется, потому что мы подсчитываем // сопоставляем индексы с 1, потому что 0 - весь результат согласованной строки [matchNames [index - 1]] = match; return result;}, {}); } var myString = «Привет, Алекс, я Джон»; var namedMatches = namedRegexMatch (myString, / Hello ([a-z] +), я ([a-z] +) / i, ["firstPersonName", "secondPersonName"]); alert (JSON.stringify (namedMatches));

2
ответ дан Matías Fidemraizer 16 August 2018 в 03:44
поделиться
  • 1
    Это круто. Я просто думаю .. не было бы возможно создать функцию регулярного выражения, которая принимает пользовательское регулярное выражение? Так что вы можете пойти как var assocArray = Regex («hello alex, я dennis», «привет» ({hisName}. +), Я ({yourName}. +) & Quot;); – Forivin 29 August 2015 в 16:46
  • 2
    @Forivin Ясно, что вы можете пойти дальше и развить эту функцию. Нетрудно заставить его работать: D – Matías Fidemraizer 29 August 2015 в 19:38
  • 3
    Вы можете расширить объект RegExp , добавив функцию в свой прототип. – Mr. TA 16 February 2016 в 20:27
  • 4
    @ Mr.TA AFAIK, не рекомендуется расширять встроенные объекты – Matías Fidemraizer 16 February 2016 в 20:50
  • 5
    @ MatíasFidemraizer Tampoco hay que ser extremistas che ... – Emilio Grisolía 31 July 2016 в 01:36

Другое возможное решение: создать объект, содержащий имена групп и индексы.

  var regex = new RegExp ("(. *) (. *)");  var regexGroups = {FirstName: 1, LastName: 2};   

Затем используйте объектные ключи для ссылки на группы:

  var m = regex.exec («John Smith»);  var f = m [regexGroups.FirstName];   

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

47
ответ дан Mr. TA 16 August 2018 в 03:44
поделиться
6
ответ дан Yashima 16 August 2018 в 03:44
поделиться
Другие вопросы по тегам:

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