|
1 |
| -## Notes |
| 1 | +<details> |
| 2 | + <summary><strong>What does this do?</strong></summary> |
2 | 3 |
|
3 |
| -Validated against [1,117,543 generated unit tests](./test/test.js), to provide brute-force verification that the generated regex-ranges are correct. |
| 4 | +<br> |
4 | 5 |
|
5 |
| -## Usage |
| 6 | +This libary generates the `source` string to be passed to `new RegExp()` for matching a range of numbers. |
| 7 | + |
| 8 | +**Example** |
6 | 9 |
|
7 | 10 | ```js
|
8 | 11 | var toRegexRange = require('{%= name %}');
|
9 |
| - |
10 |
| -var re = new RegExp(toRegexRange('1', '99')); |
11 |
| -re.test('50'); |
12 |
| -//=> true |
| 12 | +var regex = new RegExp(toRegexRange('15', '95')); |
13 | 13 | ```
|
14 | 14 |
|
15 |
| -**Examples** |
| 15 | +A string is returned so that you can do whatever you need with it before passing it to `new RegExp()` (like adding `^` or `$` boundaries, defining flags, or combining it another string). |
16 | 16 |
|
17 |
| -```js |
18 |
| -console.log(toRegexRange('111', '555')); |
19 |
| -//=> 11[1-9]|1[2-9][0-9]|[2-4][0-9]{2}|5[0-4][0-9]|55[0-5] |
| 17 | +<br> |
20 | 18 |
|
21 |
| -console.log(toRegexRange('5', '5')); |
22 |
| -//=> 5 |
| 19 | +</details> |
23 | 20 |
|
24 |
| -console.log(toRegexRange('5', '6')); |
25 |
| -//=> [5-6] |
| 21 | +<details> |
| 22 | + <summary><strong>Why use this library?</strong></summary> |
26 | 23 |
|
27 |
| -console.log(toRegexRange('51', '229')); |
28 |
| -//=> 5[1-9]|[6-9][0-9]|1[0-9]{2}|2[0-2][0-9] |
| 24 | +<br> |
29 | 25 |
|
30 |
| -console.log(toRegexRange('29', '51')); |
31 |
| -//=> 29|[3-4][0-9]|5[0-1] |
| 26 | +### Convenience |
| 27 | + |
| 28 | +Creating regular expressions for matching numbers gets deceptively complicated pretty fast. |
| 29 | + |
| 30 | +For example, let's say you need a validation regex for matching part of a user-id, postal code, social security number, tax id, etc: |
| 31 | + |
| 32 | +- regex for matching `1` => `/1/` (easy enough) |
| 33 | +- regex for matching `1` through `5` => `/[1-5]/` (not bad...) |
| 34 | +- regex for matching `1` or `5` => `/(1|5)/` (still easy...) |
| 35 | +- regex for matching `1` through `50` => `/([1-9]|[1-4][0-9]|50)/` (uh-oh...) |
| 36 | +- regex for matching `1` through `55` => `/([1-9]|[1-4][0-9]|5[0-5])/` (no prob, I can do this...) |
| 37 | +- regex for matching `1` through `555` => `/([1-9]|[1-9][0-9]|[1-4][0-9]{2}|5[0-4][0-9]|55[0-5])/` (maybe not...) |
| 38 | +- regex for matching `0001` through `5555` => `/(0{3}[1-9]|0{2}[1-9][0-9]|0[1-9][0-9]{2}|[1-4][0-9]{3}|5[0-4][0-9]{2}|55[0-4][0-9]|555[0-5])/` (okay, I get the point!) |
| 39 | + |
| 40 | +The numbers are contrived, but they're also really basic. In the real world you might need to generate a regex on-the-fly for validation. |
| 41 | + |
| 42 | +**Learn more** |
| 43 | + |
| 44 | +If you're interested in learning more about [character classes](http://www.regular-expressions.info/charclass.html) and other regex features, I personally have always found [regular-expressions.info](http://www.regular-expressions.info/charclass.html) to be pretty useful. |
| 45 | + |
| 46 | + |
| 47 | +### Heavily tested |
| 48 | + |
| 49 | +As of {%= date() %}, this library runs [2,783,483 test assertions](./test/test.js) against generated regex-ranges to provide brute-force verification that results are indeed correct. |
| 50 | + |
| 51 | +Tests run in ~870ms on my MacBook Pro, 2.5 GHz Intel Core i7. |
| 52 | + |
| 53 | +### Highly optimized |
| 54 | + |
| 55 | +Generated regular expressions are highly optimized: |
| 56 | +- duplicate sequences and character classes are reduced using quantifiers |
| 57 | +- smart enough to use `?` conditionals when number(s) or range(s) can be positive or negative |
| 58 | +- uses fragment caching to avoid processing the same exact string more than once |
| 59 | + |
| 60 | +<br> |
| 61 | + |
| 62 | +</details> |
| 63 | + |
| 64 | +## Usage |
| 65 | + |
| 66 | +Add this library to your javascript application with the following line of code |
32 | 67 |
|
33 |
| -console.log(toRegexRange('1', '100000')); |
34 |
| -//=> [1-9]|[1-9][0-9]{1,4}|100000 |
| 68 | +```js |
| 69 | +var toRegexRange = require('{%= name %}'); |
35 | 70 | ```
|
36 | 71 |
|
37 |
| -When the `min` is larger than the `max`, values will be flipped to create a valid range: |
| 72 | +The main export is a function that takes two integers: the `min` value and `max` value (formatted as strings or numbers). |
38 | 73 |
|
39 | 74 | ```js
|
40 |
| -toRegexRange('51', '29'); |
41 |
| -//=> 29|[3-4][0-9]|5[0-1] |
| 75 | +var source = toRegexRange('15', '95'); |
| 76 | +//=> 1[5-9]|[2-8][0-9]|9[0-5] |
| 77 | + |
| 78 | +var re = new RegExp('^' + source + '$'); |
| 79 | +console.log(re.test('14')); //=> false |
| 80 | +console.log(re.test('50')); //=> true |
| 81 | +console.log(re.test('94')); //=> true |
| 82 | +console.log(re.test('96')); //=> false |
42 | 83 | ```
|
43 | 84 |
|
44 |
| -**Heads up!** |
| 85 | +## Examples |
45 | 86 |
|
46 |
| -This library does not support steps (increments) or zero-padding. |
| 87 | +{%= rangeExamples() %} |
47 | 88 |
|
48 |
| -## History |
| 89 | +## Heads up! |
| 90 | + |
| 91 | +**Order of arguments** |
| 92 | + |
| 93 | +When the `min` is larger than the `max`, values will be flipped to create a valid range: |
| 94 | + |
| 95 | +```js |
| 96 | +toRegexRange('51', '29'); |
| 97 | +``` |
49 | 98 |
|
50 |
| -### v1.0 |
| 99 | +Is effectively flipped to: |
51 | 100 |
|
52 |
| -More optimizations! As of v1.0, repeating ranges are now grouped using quantifiers. Processing time is roughly the same, but the generated regex is much smaller, which should result in faster matching. |
| 101 | +```js |
| 102 | +toRegexRange('29', '51'); |
| 103 | +//=> 29|[3-4][0-9]|5[0-1] |
| 104 | +``` |
53 | 105 |
|
54 |
| -**Key** |
| 106 | +**Steps / increments** |
55 | 107 |
|
56 |
| -_(for the before/after comparison tables)_ |
| 108 | +This library does not support steps (increments). A pr to add support would be welcome. |
57 | 109 |
|
58 |
| -- `range`: the generated range, e.g. `toRegexRange(1, 10000000)` |
59 |
| -- `stats`: size of the generated string, and processing time |
60 |
| -- `result`: generated string |
61 | 110 |
|
62 |
| -#### Before |
| 111 | +## History |
| 112 | + |
| 113 | +### v2.0.0 - 2017-04-21 |
63 | 114 |
|
64 |
| -Patterns generated before v1.0 changes: |
| 115 | +**New features** |
65 | 116 |
|
66 |
| -**Range** | **Stats** | **Result** |
67 |
| ---- | --- | --- |
68 |
| -`1..10000000` | `99 B` (11ms 666μs) | `([1-9]|[1-9][0-9]|[1-9][0-9]{2}|[1-9][0-9]{3}|[1-9][0-9]{4}|[1-9][0-9]{5}|[1-9][0-9]{6}|10000000)` |
69 |
| -`1..1000000` | `84 B` (2ms 96μs) | `([1-9]|[1-9][0-9]|[1-9][0-9]{2}|[1-9][0-9]{3}|[1-9][0-9]{4}|[1-9][0-9]{5}|1000000)` |
70 |
| -`1..100000` | `69 B` (1ms 674μs) | `([1-9]|[1-9][0-9]|[1-9][0-9]{2}|[1-9][0-9]{3}|[1-9][0-9]{4}|100000)` |
71 |
| -`1..10000` | `54 B` (2ms 40μs) | `([1-9]|[1-9][0-9]|[1-9][0-9]{2}|[1-9][0-9]{3}|10000)` |
72 |
| -`1..1000` | `39 B` (1ms 263μs) | `([1-9]|[1-9][0-9]|[1-9][0-9]{2}|1000)` |
73 |
| -`1..100` | `24 B` (1ms 905μs) | `([1-9]|[1-9][0-9]|100)` |
74 |
| -`1..10` | `12 B` (383μs) | `([1-9]|10)` |
75 |
| -`1..3` | `9 B` (260μs) | `([1-3])` |
| 117 | +Adds support for zero-padding! |
76 | 118 |
|
77 |
| -#### After |
| 119 | +### v1.0.0 |
78 | 120 |
|
79 |
| -With v1.0 optimizations. |
| 121 | +**Optimizations** |
80 | 122 |
|
81 |
| -**Range** | **Stats** | **Result** |
82 |
| ---- | --- | --- |
83 |
| -`1..10000000` | `34 B` (11ms 702μs) | `([1-9]|[1-9][0-9]{1,6}|10000000)` |
84 |
| -`1..1000000` | `33 B` (1ms 274μs) | `([1-9]|[1-9][0-9]{1,5}|1000000)` |
85 |
| -`1..100000` | `32 B` (726μs) | `([1-9]|[1-9][0-9]{1,4}|100000)` |
86 |
| -`1..10000` | `31 B` (2ms 432μs) | `([1-9]|[1-9][0-9]{1,3}|10000)` |
87 |
| -`1..1000` | `30 B` (507μs) | `([1-9]|[1-9][0-9]{1,2}|1000)` |
88 |
| -`1..100` | `24 B` (267μs) | `([1-9]|[1-9][0-9]|100)` |
89 |
| -`1..10` | `12 B` (240μs) | `([1-9]|10)` |
90 |
| -`1..3` | `9 B` (665μs) | `([1-3])` |
| 123 | +Repeating ranges are now grouped using quantifiers. rocessing time is roughly the same, but the generated regex is much smaller, which should result in faster matching. |
91 | 124 |
|
92 | 125 | ## Attribution
|
93 | 126 |
|
94 |
| -Inspired by the python lib [range-regex](https://github.com/dimka665/range-regex). |
| 127 | +Inspired by the python library [range-regex](https://github.com/dimka665/range-regex). |
0 commit comments