class StringRandom
strrand.rb: Generates a random string from a pattern¶ ↑
- Author
-
tama <repeatedly@gmail.com>
StringRandom
is derived from the String::Random written in Perl. See search.cpan.org/~steve/String-Random-0.22/
Example¶ ↑
string_random = StringRandom.new string_random.random_pattern('CCcc!ccn') #=> ZIop$ab1
refer to test/test_stringrandom.rb
Format¶ ↑
Regular expression syntax¶ ↑
*_regex methods use this rule.
The following regular expression elements are supported.
- w
-
Alphanumeric + “_”.
- d
-
Digits.
- W
-
Printable characters other than those in w.
- D
-
Printable characters other than those in d.
- .
-
Printable characters.
- []
-
Character classes.
- {}
-
Repetition.
- *
-
Same as {0,}.
- +
-
Same as {1,}
- ?
-
Same as {0,1}.
Patterns¶ ↑
random_pattern
and random_string
methods use this rule.
The following patterns are pre-defined.
- c
-
Any
lowercase character [a-z] - C
-
Any
uppercase character [A-Z] - n
-
Any
digit [0-9] - !
-
A punctuation character [~`!@$%^&*()-_+=?/#,“>
- .
-
Any
of the above - s
-
A “salt” character [A-Za-z0-9./]
- b
-
Any
binary data
Pattern
can modify and add as bellow.
string_random['C'] = ['n'] string_random['A'] = Array('A'..'Z') | Array('a'..'z')
Pattern
must be a flattened array that elements are one character. Other types cause undefined behavior(raise exception, success, etc…).
Constants
- Any
- Binary
- Digit
- Lower
- OldPattern
These are the old patterns for random_pattern.
- Pattern
These are the regex-based patterns.
- Punct
- Salt
- Upper
Public Class Methods
max is default length for creating random string
# File lib/strrand.rb, line 122 def initialize(max = 10) @max = max @map = OldPattern.clone @regch = { "\\" => method(:regch_slash), '.' => method(:regch_dot), '[' => method(:regch_bracket), '*' => method(:regch_asterisk), '+' => method(:regch_plus), '?' => method(:regch_question), '|' => method(:regch_pipe), '{' => method(:regch_brace) } end
Singleton method version of random_regex.
# File lib/strrand.rb, line 99 def self.random_regex(patterns) StringRandom.new.random_regex(patterns) end
Same as StringRandom#random_pattern
if single argument. Optionally, references to lists containing other patterns can be passed to the function. Those lists will be used for 0 through 9 in the pattern.
# File lib/strrand.rb, line 109 def self.random_string(pattern, *pattern_list) string_random = StringRandom.new pattern_list.each_with_index do |new_pattern, i| string_random[i.to_s] = new_pattern end string_random.random_pattern(pattern) end
Public Instance Methods
Returns a random string pattern
# File lib/strrand.rb, line 168 def [](key) @map[key] end
Adds a random string pattern
pattern must be flattened array
# File lib/strrand.rb, line 177 def []=(key, pattern) @map[key] = pattern end
Returns a random string based on the concatenation of all the pattern strings in the list.
# File lib/strrand.rb, line 155 def random_pattern(patterns) return _random_pattern(patterns) unless patterns.instance_of?(Array) result = [] patterns.each do |pattern| result << _random_pattern(pattern) end result end
Returns a random string that will match the regular expression passed in the list argument.
# File lib/strrand.rb, line 141 def random_regex(patterns) return _random_regex(patterns) unless patterns.instance_of?(Array) result = [] patterns.each do |pattern| result << _random_regex(pattern) end result end
Private Instance Methods
# File lib/strrand.rb, line 204 def _random_pattern(pattern) string = '' pattern.split(//).each do |ch| raise %Q(Unknown pattern character "#{ch}"!) unless @map.has_key?(ch) string << @map[ch][rand(@map[ch].size)] end string end
# File lib/strrand.rb, line 183 def _random_regex(pattern) string = [] chars = pattern.split(//) non_ch = /[\$\^\*\(\)\+\{\}\]\?]/ # not supported chars while ch = chars.shift if @regch.has_key?(ch) @regch[ch].call(ch, chars, string) else warn "'#{ch}' not implemented. treating literally." if ch =~ non_ch string << [ch] end end result = '' string.each do |ch| result << ch[rand(ch.size)] end result end
# File lib/strrand.rb, line 262 def regch_asterisk(ch, chars, string) chars = '{0,}'.split('').concat(chars) end
# File lib/strrand.rb, line 282 def regch_brace(ch, chars, string) # { isn't closed, so treat it literally. return string << ch unless chars.include?('}') tmp = '' while ch = chars.shift and ch != '}' raise "'#{ch}' inside {} not supported" unless ch =~ /[\d,]/ tmp << ch end tmp = if tmp =~ /,/ raise "malformed range {#{tmp}}" unless tmp =~ /^(\d*),(\d*)$/ min = $1.length.nonzero? ? $1.to_i : 0 max = $2.length.nonzero? ? $2.to_i : @max raise "bad range {#{tmp}}" if min > max min == max ? min : min + rand(max - min + 1) else tmp.to_i end if tmp.nonzero? last = string.last (tmp - 1).times { string << last } else string.pop end end
# File lib/strrand.rb, line 244 def regch_bracket(ch, chars, string) tmp = [] while ch = chars.shift and ch != ']' if ch == '-' and !chars.empty? and !tmp.empty? max = chars.shift min = tmp.last tmp << min = min.succ while min < max else warn "${ch}' will be treated literally inside []" if ch =~ /\W/ tmp << ch end end raise 'unmatched []' if ch != ']' string << tmp end
# File lib/strrand.rb, line 240 def regch_dot(ch, chars, string) string << Pattern[ch] end
# File lib/strrand.rb, line 266 def regch_pipe(ch, chars, string) puts("CHARS: #{chars.join('/')}") puts("STRING: #{string.join('/')}") puts puts chars = "" end
# File lib/strrand.rb, line 274 def regch_plus(ch, chars, string) chars = '{1,}'.split('').concat(chars) end
# File lib/strrand.rb, line 278 def regch_question(ch, chars, string) chars = '{0,1}'.split('').concat(chars) end
-
The folloing methods are defined for regch. These characters are treated specially in random_regex.
+
# File lib/strrand.rb, line 220 def regch_slash(ch, chars, string) raise 'regex not terminated' if chars.empty? tmp = chars.shift if tmp == 'x' # This is supposed to be a number in hex, so # there had better be at least 2 characters left. tmp = chars.shift + chars.shift string << tmp.hex.chr elsif tmp =~ /[0-7]/ warn 'octal parsing not implemented. treating literally.' string << tmp elsif Pattern.has_key?(ch + tmp) string << Pattern[ch + tmp] else warn "'\\#{tmp}' being treated as literal '#{tmp}'" string << tmp end end