string_pattern 1.6.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +51 -0
- data/lib/string/pattern/add_to_ruby.rb +228 -11
- data/lib/string_pattern.rb +6 -2
- metadata +28 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 70bf11f69ccc9fe41a84e7314f88fb12e98d9639f9619869504b455e132bd5b5
|
4
|
+
data.tar.gz: 3ad181fe7fabbcafe4467c76c3cdba59beefc752cf8f773dc6729b6c13d7d642
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '05936978cbd0e45df53493d779c2b031001e591313578e5283348f9bfea78e1f20fa446b013d001b6d1c108d259ed7cdc12d36a8c3910e300bd976a3ab6f4fb7'
|
7
|
+
data.tar.gz: 6983689728bd7437e2937ee8c5c739bf2dea4638dc942de8ebf1451ee5525586246b135ee0a7d9251d09c8834f617d92dc47172afd3f320db9591ae6d749c955
|
data/README.md
CHANGED
@@ -5,6 +5,8 @@
|
|
5
5
|
With this gem, you can easily generate strings supplying a very simple pattern.
|
6
6
|
Also, you can validate if a text fulfills a specific pattern or even generate a string following a pattern and returning the wrong length, value... for testing your applications.
|
7
7
|
|
8
|
+
Also you can use regular expressions (Regexp) to generate strings: `/[a-z0-9]{2,5}\w+/.gen`
|
9
|
+
|
8
10
|
To do even more take a look at [nice_hash gem](https://github.com/MarioRuiz/nice_hash)
|
9
11
|
|
10
12
|
## Installation
|
@@ -102,6 +104,53 @@ The pattern needs to be a symbol object.
|
|
102
104
|
}
|
103
105
|
```
|
104
106
|
|
107
|
+
#### Generate strings using Regular Expressions (Regexp)
|
108
|
+
|
109
|
+
Take in consideration this feature is not supporting all possibilities for Regular expressions but it is fully functional. If you find any bug or limitation please add it to issues: https://github.com/MarioRuiz/string_pattern/issues
|
110
|
+
|
111
|
+
In case you you want to change the default maximum for repetitions when using * or +: `StringPattern.default_infinite = 30` . By default is 10.
|
112
|
+
|
113
|
+
If you want to translate a regular expression into an StringPattern use the method we added to Regexp class: `to_sp`
|
114
|
+
|
115
|
+
Examples:
|
116
|
+
|
117
|
+
```ruby
|
118
|
+
/[a-z0-9]{2-5}\w+/.to_sp
|
119
|
+
#> ["2-5:nx", "1-10:Ln_"]
|
120
|
+
|
121
|
+
#regular expression for UUID v4
|
122
|
+
/[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}/.to_sp
|
123
|
+
#> ["8:n[ABCDEF]", "-", "4:n[ABCDEF]", "-4", "3:n[ABCDEF]", "-", "1:[89AB]", "3:n[ABCDEF]", "-", "12:n[ABCDEF]"]
|
124
|
+
```
|
125
|
+
|
126
|
+
If you want to generate a random string following the regular expression, you can do it like a normal string pattern:
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
|
130
|
+
regexp = /[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}/
|
131
|
+
|
132
|
+
# using StringPattern class
|
133
|
+
puts StringPattern.generate(regexp)
|
134
|
+
|
135
|
+
# using Kernel
|
136
|
+
puts generate(regexp)
|
137
|
+
|
138
|
+
# using generate method added to Regexp class
|
139
|
+
puts regexp.generate
|
140
|
+
|
141
|
+
#using the alias 'gen'
|
142
|
+
puts regexp.gen
|
143
|
+
|
144
|
+
# output:
|
145
|
+
#>7009574B-6F2F-436E-BB7A-EA5FDA6B4E47
|
146
|
+
#>5FB1718F-108A-4F62-8170-33C43FD86B1D
|
147
|
+
#>05745B6F-93BA-475F-8118-DD56E5EAC4D1
|
148
|
+
#>2D6FC189-8D50-45A8-B182-780193838502
|
149
|
+
|
150
|
+
```
|
151
|
+
|
152
|
+
### String patterns
|
153
|
+
|
105
154
|
#### How to generate one or another string
|
106
155
|
|
107
156
|
In case you need to specify that the string is generated selecting one or another fixed string or pattern, you can do it by using Array of patterns and in the position you want you can add an array with the possible values
|
@@ -117,6 +166,7 @@ p ["uno:", :"5:N", ['.red','.green', :'3:L'] ].gen
|
|
117
166
|
# 'uno:34322.red'
|
118
167
|
# 'uno:44432.green'
|
119
168
|
# 'uno:34322.red'
|
169
|
+
# 'uno:28795xAB'
|
120
170
|
|
121
171
|
```
|
122
172
|
|
@@ -213,6 +263,7 @@ Examples:
|
|
213
263
|
|
214
264
|
"10:L/n/".gen errors: [:value]
|
215
265
|
#> 1hwIw;v{KQ, mpk*l]!7:!, wocipgZt8@
|
266
|
+
|
216
267
|
```
|
217
268
|
|
218
269
|
### Validate if a string is following a pattern
|
@@ -6,14 +6,14 @@ class Array
|
|
6
6
|
StringPattern.generate(self, expected_errors: expected_errors, **synonyms)
|
7
7
|
end
|
8
8
|
|
9
|
-
|
9
|
+
alias gen generate
|
10
10
|
|
11
11
|
# it will validate an string following the pattern specified
|
12
12
|
def validate(string_to_validate, expected_errors: [], not_expected_errors: [], **synonyms)
|
13
13
|
StringPattern.validate(text: string_to_validate, pattern: self, expected_errors: expected_errors, not_expected_errors: not_expected_errors, **synonyms)
|
14
14
|
end
|
15
15
|
|
16
|
-
|
16
|
+
alias val validate
|
17
17
|
end
|
18
18
|
|
19
19
|
class String
|
@@ -22,46 +22,263 @@ class String
|
|
22
22
|
StringPattern.generate(self, expected_errors: expected_errors, **synonyms)
|
23
23
|
end
|
24
24
|
|
25
|
-
|
25
|
+
alias gen generate
|
26
26
|
|
27
27
|
# it will validate an string following the pattern specified
|
28
28
|
def validate(string_to_validate, expected_errors: [], not_expected_errors: [], **synonyms)
|
29
29
|
StringPattern.validate(text: string_to_validate, pattern: self, expected_errors: expected_errors, not_expected_errors: not_expected_errors, **synonyms)
|
30
30
|
end
|
31
31
|
|
32
|
-
|
32
|
+
alias val validate
|
33
33
|
end
|
34
34
|
|
35
|
-
|
36
35
|
class Symbol
|
37
36
|
# it will generate an string following the pattern specified
|
38
37
|
def generate(expected_errors: [], **synonyms)
|
39
38
|
StringPattern.generate(self, expected_errors: expected_errors, **synonyms)
|
40
39
|
end
|
41
40
|
|
42
|
-
|
41
|
+
alias gen generate
|
43
42
|
|
44
43
|
# it will validate an string following the pattern specified
|
45
44
|
def validate(string_to_validate, expected_errors: [], not_expected_errors: [], **synonyms)
|
46
|
-
StringPattern.validate(text: string_to_validate, pattern:
|
45
|
+
StringPattern.validate(text: string_to_validate, pattern: to_s, expected_errors: expected_errors, not_expected_errors: not_expected_errors, **synonyms)
|
47
46
|
end
|
48
47
|
|
49
|
-
|
48
|
+
alias val validate
|
50
49
|
end
|
51
50
|
|
51
|
+
class Regexp
|
52
|
+
|
53
|
+
# it will generate an string following the pattern specified
|
54
|
+
def generate(expected_errors: [], **synonyms)
|
55
|
+
StringPattern.generate(self, expected_errors: expected_errors, **synonyms)
|
56
|
+
end
|
57
|
+
|
58
|
+
alias gen generate
|
59
|
+
|
60
|
+
# adds method to convert a Regexp to StringPattern
|
61
|
+
# returns an array of string patterns or just one string pattern
|
62
|
+
def to_sp
|
63
|
+
regexp_s = self.to_s
|
64
|
+
return StringPattern.cache[regexp_s] unless StringPattern.cache[regexp_s].nil?
|
65
|
+
regexp = Regexp.new regexp_s
|
66
|
+
require 'regexp_parser'
|
67
|
+
default_infinite = StringPattern.default_infinite
|
68
|
+
pata = []
|
69
|
+
pats = ''
|
70
|
+
patg = [] # for (aa|bb|cc) group
|
71
|
+
set = false
|
72
|
+
capture = false
|
73
|
+
|
74
|
+
range = ''
|
75
|
+
fixed_text=false
|
76
|
+
last_char = (regexp.to_s.gsub("?-mix:",'').length)-2
|
77
|
+
Regexp::Scanner.scan regexp do |type, token, text, ts, te|
|
78
|
+
if type == :escape
|
79
|
+
if token == :dot
|
80
|
+
token = :literal
|
81
|
+
text = '.'
|
82
|
+
elsif token == :literal and text.size == 2
|
83
|
+
text = text[1]
|
84
|
+
else
|
85
|
+
puts "Report token not controlled: type: #{type}, token: #{token}, text: '#{text}' [#{ts}..#{te}]"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
unless set || (token == :interval) || (token == :zero_or_one) ||
|
91
|
+
(token == :zero_or_more) || (token == :one_or_more) || (pats == '')
|
92
|
+
if (pats[0] == '[') && (pats[-1] == ']')
|
93
|
+
pats[0] = ''
|
94
|
+
if (token == :alternation) || !patg.empty?
|
95
|
+
if fixed_text
|
96
|
+
if patg.size==0
|
97
|
+
patg << (pata.pop + pats.chop)
|
98
|
+
else
|
99
|
+
patg[-1] += pats.chop
|
100
|
+
end
|
101
|
+
else
|
102
|
+
patg << pats.chop
|
103
|
+
end
|
104
|
+
else
|
105
|
+
if fixed_text
|
106
|
+
pata[-1]+=pats.chop
|
107
|
+
else
|
108
|
+
if pats.size==2
|
109
|
+
pata << pats.chop #jal
|
110
|
+
else
|
111
|
+
pata << "1:[#{pats}" #jal
|
112
|
+
end
|
113
|
+
if last_char==te and type==:literal and token==:literal
|
114
|
+
pata << text
|
115
|
+
pats = ""
|
116
|
+
next
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
else
|
121
|
+
if (token == :alternation) || !patg.empty?
|
122
|
+
patg << "1:#{pats}"
|
123
|
+
else
|
124
|
+
pata << "1:#{pats}"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
pats = ''
|
128
|
+
end
|
129
|
+
fixed_text=false
|
130
|
+
|
131
|
+
case token
|
132
|
+
when :open
|
133
|
+
set = true
|
134
|
+
pats += '['
|
135
|
+
when :close
|
136
|
+
if type == :set
|
137
|
+
set = false
|
138
|
+
if pats[-1] == '['
|
139
|
+
pats.chop!
|
140
|
+
else
|
141
|
+
pats += ']'
|
142
|
+
end
|
143
|
+
elsif type == :group
|
144
|
+
capture = false
|
145
|
+
unless patg.empty?
|
146
|
+
patg << pats if pats.to_s != ''
|
147
|
+
pata << patg
|
148
|
+
patg = []
|
149
|
+
pats = ''
|
150
|
+
end
|
151
|
+
end
|
152
|
+
when :capture
|
153
|
+
capture = true if type == :group
|
154
|
+
when :alternation
|
155
|
+
if type == :meta
|
156
|
+
if pats != ''
|
157
|
+
patg << pats
|
158
|
+
pats = ''
|
159
|
+
elsif patg.empty?
|
160
|
+
# for the case the first element was not added to patg and was on pata fex: (a+|b|c)
|
161
|
+
patg << pata.pop
|
162
|
+
end
|
163
|
+
end
|
164
|
+
when :range
|
165
|
+
range = pats[-1]
|
166
|
+
pats.chop!
|
167
|
+
when :digit
|
168
|
+
pats += 'n'
|
169
|
+
when :nondigit
|
170
|
+
pats += '*[%0123456789%]'
|
171
|
+
when :space
|
172
|
+
pats += '_'
|
173
|
+
when :nonspace
|
174
|
+
pats += '*[% %]'
|
175
|
+
when :word
|
176
|
+
pats += 'Ln_'
|
177
|
+
when :nonword
|
178
|
+
pats += '$'
|
179
|
+
when :word_boundary
|
180
|
+
pats += '$'
|
181
|
+
when :dot
|
182
|
+
pats += '*'
|
183
|
+
when :literal
|
184
|
+
if range == ''
|
185
|
+
if text.size > 1
|
186
|
+
fixed_text=true
|
187
|
+
if !patg.empty?
|
188
|
+
patg << text.chop
|
189
|
+
else
|
190
|
+
pata << text.chop
|
191
|
+
end
|
192
|
+
pats = text[-1]
|
193
|
+
else
|
194
|
+
pats += text
|
195
|
+
end
|
196
|
+
else
|
197
|
+
range = range + '-' + text
|
198
|
+
if range == 'a-z'
|
199
|
+
pats = 'x' + pats
|
200
|
+
elsif range == 'A-Z'
|
201
|
+
pats = 'X' + pats
|
202
|
+
elsif range == '0-9'
|
203
|
+
pats = 'n' + pats
|
204
|
+
else
|
205
|
+
pats += if set
|
206
|
+
(range[0]..range[2]).to_a.join
|
207
|
+
else
|
208
|
+
'[' + (range[0]..range[2]).to_a.join + ']'
|
209
|
+
end
|
210
|
+
|
211
|
+
end
|
212
|
+
range = ''
|
213
|
+
end
|
214
|
+
pats = '[' + pats + ']' unless set
|
215
|
+
when :interval
|
216
|
+
size = text.sub(',', '-').sub('{', '').sub('}', '')
|
217
|
+
size.chop! if size[-1] == '-'
|
218
|
+
pats = size + ':' + pats
|
219
|
+
if !patg.empty?
|
220
|
+
patg << pats
|
221
|
+
else
|
222
|
+
pata << pats
|
223
|
+
end
|
224
|
+
pats = ''
|
225
|
+
when :zero_or_one
|
226
|
+
pats = '0-1:' + pats
|
227
|
+
if !patg.empty?
|
228
|
+
patg << pats
|
229
|
+
else
|
230
|
+
pata << pats
|
231
|
+
end
|
232
|
+
pats = ''
|
233
|
+
when :zero_or_more
|
234
|
+
pats = "0-#{default_infinite}:" + pats
|
235
|
+
if !patg.empty?
|
236
|
+
patg << pats
|
237
|
+
else
|
238
|
+
pata << pats
|
239
|
+
end
|
240
|
+
pats = ''
|
241
|
+
when :one_or_more
|
242
|
+
pats = "1-#{default_infinite}:" + pats
|
243
|
+
if !patg.empty?
|
244
|
+
patg << pats
|
245
|
+
else
|
246
|
+
pata << pats
|
247
|
+
end
|
248
|
+
pats = ''
|
249
|
+
end
|
250
|
+
end
|
251
|
+
if pats!=""
|
252
|
+
if pata.empty?
|
253
|
+
if pats[0]=="[" and pats[-1]=="]" #fex: /[12ab]/
|
254
|
+
pata = ["1:#{pats}"]
|
255
|
+
end
|
256
|
+
else
|
257
|
+
pata[-1]+=pats[1] #fex: /allo/
|
258
|
+
end
|
259
|
+
end
|
260
|
+
if pata.size==1 and pata[0].kind_of?(String)
|
261
|
+
res = pata[0]
|
262
|
+
else
|
263
|
+
res = pata
|
264
|
+
end
|
265
|
+
StringPattern.cache[regexp_s] = res
|
266
|
+
return res
|
267
|
+
end
|
268
|
+
end
|
52
269
|
|
53
270
|
module Kernel
|
54
271
|
public
|
272
|
+
|
55
273
|
# if string or symbol supplied it will generate a string with the supplied pattern specified on the string
|
56
274
|
# if array supplied then it will generate a string with the supplied patterns. If a position contains a pattern supply it as symbol, for example: [:"10:N", "fixed", :"10-20:XN/x/"]
|
57
275
|
def generate(pattern, expected_errors: [], **synonyms)
|
58
|
-
if pattern.
|
276
|
+
if pattern.is_a?(String) || pattern.is_a?(Array) || pattern.is_a?(Symbol) || pattern.is_a?(Regexp)
|
59
277
|
StringPattern.generate(pattern, expected_errors: expected_errors, **synonyms)
|
60
278
|
else
|
61
279
|
puts " Kernel generate method: class not recognized:#{pattern.class}"
|
62
280
|
end
|
63
281
|
end
|
64
282
|
|
65
|
-
|
283
|
+
alias gen generate
|
66
284
|
end
|
67
|
-
|
data/lib/string_pattern.rb
CHANGED
@@ -18,15 +18,18 @@ require_relative 'string/pattern/add_to_ruby' if SP_ADD_TO_RUBY
|
|
18
18
|
# If true it will check on the strings of the array positions if they have the pattern format and assume in that case that is a pattern.
|
19
19
|
# dont_repeat: (TrueFalse, default: false)
|
20
20
|
# If you want to generate for example 1000 strings and be sure all those strings are different you can set it to true
|
21
|
+
# default_infinite: (Integer, default: 10)
|
22
|
+
# In case using regular expressions the maximum when using * or + for repetitions
|
21
23
|
class StringPattern
|
22
24
|
class << self
|
23
|
-
attr_accessor :national_chars, :optimistic, :dont_repeat, :cache, :cache_values
|
25
|
+
attr_accessor :national_chars, :optimistic, :dont_repeat, :cache, :cache_values, :default_infinite
|
24
26
|
end
|
25
27
|
@national_chars = (('a'..'z').to_a + ('A'..'Z').to_a).join
|
26
28
|
@optimistic = true
|
27
29
|
@cache = Hash.new()
|
28
30
|
@cache_values = Hash.new()
|
29
31
|
@dont_repeat = false
|
32
|
+
@default_infinite = 10
|
30
33
|
NUMBER_SET = ('0'..'9').to_a
|
31
34
|
SPECIAL_SET = [' ', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '_', '+', '=', '{', '}', '[', ']', "'", ';', ':', '?', '>', '<', '`', '|', '/', '"']
|
32
35
|
ALPHA_SET_LOWER = ('a'..'z').to_a
|
@@ -346,7 +349,8 @@ class StringPattern
|
|
346
349
|
end
|
347
350
|
end
|
348
351
|
string_set_not_allowed = Array.new
|
349
|
-
|
352
|
+
elsif pattern.kind_of?(Regexp)
|
353
|
+
return generate(pattern.to_sp, expected_errors: expected_errors)
|
350
354
|
else
|
351
355
|
puts "pattern argument not valid on StringPattern.generate: #{pattern.inspect}, expected_errors: #{expected_errors.inspect}"
|
352
356
|
return pattern.to_s
|
metadata
CHANGED
@@ -1,18 +1,39 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: string_pattern
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mario Ruiz
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-01-
|
12
|
-
dependencies:
|
11
|
+
date: 2019-01-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: regexp_parser
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.3.0
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.3'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.3.0
|
13
33
|
description: 'You can easily generate strings supplying a very simple pattern. ''10-20:Xn/x/''.generate
|
14
|
-
#>qBstvc6JN8ra.
|
15
|
-
|
34
|
+
#>qBstvc6JN8ra. Now generate random strings using a regular expression (Regexp):
|
35
|
+
/[a-z0-9]{2,5}w+/.gen . Also, you can validate if a text fulfills a specific pattern
|
36
|
+
or even generate a string following a pattern and returning the wrong length, value...
|
16
37
|
for testing your applications.'
|
17
38
|
email: marioruizs@gmail.com
|
18
39
|
executables: []
|
@@ -49,6 +70,6 @@ rubyforge_project:
|
|
49
70
|
rubygems_version: 2.7.6
|
50
71
|
signing_key:
|
51
72
|
specification_version: 4
|
52
|
-
summary: 'Generate easily random strings following a simple pattern
|
53
|
-
#>qBstvc6JN8ra'
|
73
|
+
summary: 'Generate easily random strings following a simple pattern or regular expression.
|
74
|
+
''10-20:Xn/x/''.generate #>qBstvc6JN8ra'
|
54
75
|
test_files: []
|