├── LICENSE ├── README.md └── TODO.md /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Rinat Mukhatrov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Регулярные выражения 2 | 3 | ## Когда применять, а когда не применять регулярные выражения? 4 | 5 | Если вы пишите прототип, или если скорость работы не принципиальна — используйте [регулярные выражения](https://github.com/ziishaned/learn-regex/blob/master/translations/README-ru.md). Это ускорит скорость разработки и уменьшит количество кода. Но, если итоговое решение будет работать медленно, то его всегда можно будет переписать без использования регулярных выражений. 6 | 7 | ## Диалекты 8 | * [PCRE](http://www.pcre.org/current/doc/html/pcre2syntax.html), применяется в [PHP](http://php.net/) и др. ПО 9 | * [ECMA 262](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Regular_Expressions), применяется в [JavaScript](https://developer.mozilla.org/docs/Web/JavaScript) 10 | * есть и [другие](https://en.wikipedia.org/wiki/Comparison_of_regular_expression_engines) достойные внимания, но в этом документе не рассматриваются 11 | 12 | ## Функции и методы объектов для обработки строк регулярными выражениями в языках программирования 13 | Тип обработки|JavaScript|PHP 14 | -------------|----------|--- 15 | Проверка соответствия (валидация)| [`RegExp.test()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test)|[`preg_match()`](http://php.net/manual/function.preg-match.php), [`preg_grep()`](http://php.net/manual/function.preg-grep.php) 16 | Поиск и захват подстрок| [`RegExp.exec()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec), [`String.match()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/match), [`String.search()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/search)|[`preg_match_all()`](http://php.net/manual/function.preg-match-all.php) 17 | Поиск, захват и замена подстрок| [`String.replace()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/replace)|[`preg_replace()`](http://php.net/manual/en/function.preg-replace.php), [`preg_replace_callback()`](http://php.net/manual/function.preg-replace-callback.php), [`preg_replace_callback_array()`](http://php.net/manual/function.preg-replace-callback-array.php), [`preg_filter()`](http://php.net/manual/function.preg-filter.php) 18 | Поиск и разбиение на подстроки| [`String.split()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/split)|[`preg_split()`](http://php.net/manual/function.preg-split.php) 19 | 20 | ## Виды соответствия 21 | * Полное — вся строка соответствует шаблону регулярного выражения, которое всегда начинается с `^` и заканчивается на `$`. 22 | * Частичное — часть строки соответствует шаблону регулярного выражения. Наличие символов `^` и `$` опционально. 23 | 24 | Полное соответствие обычно используют для [валидации](https://en.wikipedia.org/wiki/Data_validation) (проверки) строк на соответствие или не соответствие регулярному выражению. А частичное — для [синтаксического анализа](https://ru.wikipedia.org/wiki/Синтаксический_анализ) (парсинга) и [лексического анализа](https://ru.wikipedia.org/wiki/Лексический_анализ) (токенизации) строк. 25 | 26 | Из частичного соответствия очень легко сделать полное, указав `^` в начале и `$` в конце. В обратную сторону — сложнее, т.к. при необходимости необходимо явно указывать границы начала и конца искомой подстроки. Обычно это делают через `(?…)` и/или [однократные квантификаторы](https://www.regular-expressions.info/possessive.html): `…?+`, `…*+`, `…++`. В диалекте JS нет такой встроенной возможности, но можно использовать конструкцию типа `(?=(…))\1`, которая является аналогом. 36 | 2. Не используйте вложенные циклы типа `(…+)+`. Используйте конструкции типа `(?!…)(…)+`, `(?=…)(…)+`, `(…)+(?` там, где они пропущены (чинит некорректную вложенность тегов `
  • `): [PCRE](https://regex101.com/r/PFEWtT/7/) 180 | 181 | ### Обработка естественного языка 182 | * Удаление начальных и конечных пробелов: [PCRE](https://regex101.com/r/JM7xw4/1) 183 | * Валидация слова на английском языке во множественном числе: [PCRE](https://regex101.com/r/GtF2QA/9/) 184 | * Валидация ФИО на русском или английском языке: [PCRE](https://regex101.com/r/GQ1xKK/17/) 185 | * Выделение слов и чисел из текста [PCRE](https://regex101.com/r/fpu9Gb/2/) 186 | * Поиск дубликатов в списке через запятую [PCRE](https://regex101.com/r/GTH0Kr/2/) 187 | 188 | ### SQL 189 | * Детектирование SQL на модификацию данных: [PCRE](https://regex101.com/r/CcSugS/17) 190 | 191 | ### PostgreSQL v10+ 192 | * Разбиение SQL на несколько запросов по символу `;`: [PCRE](https://regex101.com/r/nj3z8j/5) 193 | 194 | Захват квотированной строки (PCRE): 195 | ```regexp 196 | (?> 197 | '(?>[^']+|'')*' #string constants 198 | | \b[Ee]'(?>[^\\']+|''|\\.)*' #string constants with C-style escapes 199 | | (?\$[a-zA-Z\d_]*\$) #dollar-quoted string 200 | [^$]*+ #speed improves 201 | .*? 202 | \k 203 | ) 204 | ``` 205 | 206 | Захват квотированного названия объекта БД (PCRE): 207 | ```regexp 208 | "(?>[^"]+|"")*" 209 | ``` 210 | 211 | Захват комментариев (PCRE): 212 | ```regexp 213 | (?> 214 | #singe-line comment 215 | (?-- [^\r\n]*+) 216 | | 217 | #multi-line comment 218 | (? 219 | /\* 220 | [^*/]*+ 221 | (?> [^*/]++ 222 | | \*[^/] 223 | | /[^*] 224 | | (?&MutilineComment) #recursive 225 | )*+ 226 | \*/ 227 | ) 228 | ) 229 | ``` 230 | 231 | ### MySQL v8+ 232 | 233 | Захват квотированной строки (PCRE): 234 | ```regexp 235 | (?>"(?>[^\\"]+|""|\\.)*"|'(?>[^\\']+|''|\\.)*') 236 | ``` 237 | 238 | Захват квотированного названия объекта БД (PCRE): 239 | ```regexp 240 | `(?>[^\\`]+|``|\\.)*` 241 | ``` 242 | 243 | Захват комментариев (PCRE): 244 | ```regexp 245 | (?> 246 | #singe-line comment 247 | (?-- (?=\s) [^\r\n]*+) 248 | | 249 | #multi-line comment by Jeffrey Friedl (fastest) 250 | (? 251 | /\* 252 | [^*]* \*+ 253 | (?:[^*/][^*]*\*+)* 254 | / 255 | ) 256 | ) 257 | ``` 258 | 259 | ### ClickHouse v1+ 260 | 261 | Захват квотированной строки (PCRE): 262 | ```regexp 263 | '(?>[^\\']+|''|\\.)*' 264 | ``` 265 | 266 | Захват квотированного названия объекта БД (PCRE): 267 | ```regexp 268 | (?>"(?>[^\\"]+|""|\\.)*"|`(?>[^\\`]+|``|\\.)*`) 269 | ``` 270 | 271 | Захват комментариев (PCRE): 272 | ```regexp 273 | (?> 274 | #singe-line comment 275 | -- [^\r\n]*+ 276 | | 277 | #multi-line comment by Jeffrey Friedl (fastest) 278 | /\* 279 | [^*]* \*+ 280 | (?:[^*/][^*]*\*+)* 281 | / 282 | ) 283 | ``` 284 | 285 | ### Прочее 286 | * Валидация (неполная, но быстрая) регулярного выражения на диалект ECMA 262 (JavaScript), есть проверка на уникальность флагов: [PCRE](https://regex101.com/r/iB63bg/3/) 287 | 288 | 289 | ### Валидация качества пароля 290 | 291 | Регулярное выражение: [PCRE](https://regex101.com/r/MOWCV3/12) 292 | 293 | Пароль должен соответствовать следующим требованиям: 294 | 1. длина от 8 до 72 символов (72 символа — это ограничение алгоритма [bf](https://postgrespro.ru/docs/postgresql/11/pgcrypto#PGCRYPTO-CRYPT-ALGORITHMS)) 295 | 2. допускаются только цифры, английские буквы и знаки пунктуации 296 | 3. содержит хотябы одну цифру (0-9) 297 | 4. содержит хотябы одну английскую прописную букву (A-Z) 298 | 5. содержит хотябы одну английскую строчную букву (a-z) 299 | 6. содержит хотябы один знак пунктуации: `!"#$%&'()*+,-./:;<=>?@[\]^_``{|}~` 300 | 7. не имеют 6 и более подряд совпадающих символов типа "zzzzzz", "000000" 301 | 8. не имеет "плохих" последовательностей типа "123456", "abcdef", "qwerty" 302 | 303 | ### Парсинг CSV 304 | 305 | * Захват только непустых значений колонок: [PCRE](https://regex101.com/r/ZRP2iA/2) 306 | * Как распарсить CSV строку в таблицу? [PCRE](https://regex101.com/r/3yJVNR/3), [PostgreSQL](https://github.com/rin-nas/postgresql-patterns-library/blob/master/README.md#%D0%BA%D0%B0%D0%BA-%D1%80%D0%B0%D1%81%D0%BF%D0%B0%D1%80%D1%81%D0%B8%D1%82%D1%8C-csv-%D1%81%D1%82%D1%80%D0%BE%D0%BA%D1%83-%D0%B2-%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%83) 307 | 308 | ### Детектирование бинарных данных 309 | 310 | Ищем до первого найденного [управляющего символа](https://unicode-table.com/ru/#control-character) по регулярному выражению `/[\x00-\x1f](? 44 | // MIT License 45 | 46 | function parseUri (str) { 47 | var o = parseUri.options, 48 | m = o.parser[o.strictMode ? "strict" : "loose"].exec(str), 49 | uri = {}, 50 | i = 14; 51 | 52 | while (i--) uri[o.key[i]] = m[i] || ""; 53 | 54 | uri[o.q.name] = {}; 55 | uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) { 56 | if ($1) uri[o.q.name][$1] = $2; 57 | }); 58 | 59 | return uri; 60 | }; 61 | 62 | parseUri.options = { 63 | strictMode: false, 64 | key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], 65 | q: { 66 | name: "queryKey", 67 | parser: /(?:^|&)([^&=]*)=?([^&]*)/g 68 | }, 69 | parser: { 70 | strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, 71 | loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ 72 | } 73 | }; 74 | 75 | ``` 76 | 77 | 78 | Примеры настоящих фамилий и имён, которые не пройдут валидацию по регулярке проверки ФИО 79 | ``` 80 | Mkrtchyan 81 | Mkrtchian 82 | Mkrtcyn 83 | Hoghmrtsyan 84 | Kbiltsetskhlashvili 85 | Aiya 86 | Хауеева 87 | Sayyod 88 | ``` 89 | --------------------------------------------------------------------------------