├── 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 |
--------------------------------------------------------------------------------