line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# String::Random - Generates a random string from a pattern |
2
|
|
|
|
|
|
|
# Copyright (C) 1999-2006 Steven Pritchard |
3
|
|
|
|
|
|
|
# |
4
|
|
|
|
|
|
|
# This program is free software; you can redistribute it |
5
|
|
|
|
|
|
|
# and/or modify it under the same terms as Perl itself. |
6
|
|
|
|
|
|
|
# |
7
|
|
|
|
|
|
|
# This program is distributed in the hope that it will be useful, |
8
|
|
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
9
|
|
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
10
|
|
|
|
|
|
|
# |
11
|
|
|
|
|
|
|
# $Id: Random.pm,v 1.4 2006/09/21 17:34:07 steve Exp $ |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
package String::Random; |
14
|
|
|
|
|
|
|
$String::Random::VERSION = '0.31'; |
15
|
|
|
|
|
|
|
require 5.006_001; |
16
|
|
|
|
|
|
|
|
17
|
7
|
|
|
7
|
|
440449
|
use strict; |
|
7
|
|
|
|
|
66
|
|
|
7
|
|
|
|
|
254
|
|
18
|
7
|
|
|
7
|
|
34
|
use warnings; |
|
7
|
|
|
|
|
10
|
|
|
7
|
|
|
|
|
167
|
|
19
|
|
|
|
|
|
|
|
20
|
7
|
|
|
7
|
|
29
|
use Carp; |
|
7
|
|
|
|
|
12
|
|
|
7
|
|
|
|
|
331
|
|
21
|
7
|
|
|
7
|
|
3146
|
use parent qw(Exporter); |
|
7
|
|
|
|
|
1990
|
|
|
7
|
|
|
|
|
32
|
|
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
our %EXPORT_TAGS = ( |
24
|
|
|
|
|
|
|
'all' => [ |
25
|
|
|
|
|
|
|
qw( |
26
|
|
|
|
|
|
|
&random_string |
27
|
|
|
|
|
|
|
&random_regex |
28
|
|
|
|
|
|
|
) |
29
|
|
|
|
|
|
|
] |
30
|
|
|
|
|
|
|
); |
31
|
|
|
|
|
|
|
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
# These are the various character sets. |
34
|
|
|
|
|
|
|
my @upper = ( 'A' .. 'Z' ); |
35
|
|
|
|
|
|
|
my @lower = ( 'a' .. 'z' ); |
36
|
|
|
|
|
|
|
my @digit = ( '0' .. '9' ); |
37
|
|
|
|
|
|
|
my @punct = map {chr} ( 33 .. 47, 58 .. 64, 91 .. 96, 123 .. 126 ); |
38
|
|
|
|
|
|
|
my @any = ( @upper, @lower, @digit, @punct ); |
39
|
|
|
|
|
|
|
my @salt = ( @upper, @lower, @digit, '.', '/' ); |
40
|
|
|
|
|
|
|
my @binary = map {chr} ( 0 .. 255 ); |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
# What's important is how they relate to the pattern characters. |
43
|
|
|
|
|
|
|
# These are the old patterns for randpattern/random_string. |
44
|
|
|
|
|
|
|
my %old_patterns = ( |
45
|
|
|
|
|
|
|
'C' => [@upper], |
46
|
|
|
|
|
|
|
'c' => [@lower], |
47
|
|
|
|
|
|
|
'n' => [@digit], |
48
|
|
|
|
|
|
|
'!' => [@punct], |
49
|
|
|
|
|
|
|
'.' => [@any], |
50
|
|
|
|
|
|
|
's' => [@salt], |
51
|
|
|
|
|
|
|
'b' => [@binary], |
52
|
|
|
|
|
|
|
); |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
# These are the regex-based patterns. |
55
|
|
|
|
|
|
|
my %patterns = ( |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
# These are the regex-equivalents. |
58
|
|
|
|
|
|
|
'.' => [@any], |
59
|
|
|
|
|
|
|
'\d' => [@digit], |
60
|
|
|
|
|
|
|
'\D' => [ @upper, @lower, @punct ], |
61
|
|
|
|
|
|
|
'\w' => [ @upper, @lower, @digit, '_' ], |
62
|
|
|
|
|
|
|
'\W' => [ grep { $_ ne '_' } @punct ], |
63
|
|
|
|
|
|
|
'\s' => [ q{ }, "\t" ], # Would anything else make sense? |
64
|
|
|
|
|
|
|
'\S' => [ @upper, @lower, @digit, @punct ], |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
# These are translated to their double quoted equivalents. |
67
|
|
|
|
|
|
|
'\t' => ["\t"], |
68
|
|
|
|
|
|
|
'\n' => ["\n"], |
69
|
|
|
|
|
|
|
'\r' => ["\r"], |
70
|
|
|
|
|
|
|
'\f' => ["\f"], |
71
|
|
|
|
|
|
|
'\a' => ["\a"], |
72
|
|
|
|
|
|
|
'\e' => ["\e"], |
73
|
|
|
|
|
|
|
); |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
# This is used for cache of parsed range patterns in %regch |
76
|
|
|
|
|
|
|
my %parsed_range_patterns = (); |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
# These characters are treated specially in randregex(). |
79
|
|
|
|
|
|
|
my %regch = ( |
80
|
|
|
|
|
|
|
'\\' => sub { |
81
|
|
|
|
|
|
|
my ( $self, $ch, $chars, $string ) = @_; |
82
|
|
|
|
|
|
|
if ( @{$chars} ) { |
83
|
|
|
|
|
|
|
my $tmp = shift( @{$chars} ); |
84
|
|
|
|
|
|
|
if ( $tmp eq 'x' ) { |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
# This is supposed to be a number in hex, so |
87
|
|
|
|
|
|
|
# there had better be at least 2 characters left. |
88
|
|
|
|
|
|
|
$tmp = shift( @{$chars} ) . shift( @{$chars} ); |
89
|
|
|
|
|
|
|
push( @{$string}, [ chr( hex($tmp) ) ] ); |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
elsif ( $tmp =~ /[0-7]/ ) { |
92
|
|
|
|
|
|
|
carp 'octal parsing not implemented. treating literally.'; |
93
|
|
|
|
|
|
|
push( @{$string}, [$tmp] ); |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
elsif ( defined( $patterns{"\\$tmp"} ) ) { |
96
|
|
|
|
|
|
|
$ch .= $tmp; |
97
|
|
|
|
|
|
|
push( @{$string}, $patterns{$ch} ); |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
else { |
100
|
|
|
|
|
|
|
if ( $tmp =~ /\w/ ) { |
101
|
|
|
|
|
|
|
carp "'\\$tmp' being treated as literal '$tmp'"; |
102
|
|
|
|
|
|
|
} |
103
|
|
|
|
|
|
|
push( @{$string}, [$tmp] ); |
104
|
|
|
|
|
|
|
} |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
else { |
107
|
|
|
|
|
|
|
croak 'regex not terminated'; |
108
|
|
|
|
|
|
|
} |
109
|
|
|
|
|
|
|
}, |
110
|
|
|
|
|
|
|
'.' => sub { |
111
|
|
|
|
|
|
|
my ( $self, $ch, $chars, $string ) = @_; |
112
|
|
|
|
|
|
|
push( @{$string}, $patterns{$ch} ); |
113
|
|
|
|
|
|
|
}, |
114
|
|
|
|
|
|
|
'[' => sub { |
115
|
|
|
|
|
|
|
my ( $self, $ch, $chars, $string ) = @_; |
116
|
|
|
|
|
|
|
my @tmp; |
117
|
|
|
|
|
|
|
while ( defined( $ch = shift( @{$chars} ) ) && ( $ch ne ']' ) ) { |
118
|
|
|
|
|
|
|
if ( ( $ch eq '-' ) && @{$chars} && @tmp ) { |
119
|
|
|
|
|
|
|
my $begin_ch = $tmp[-1]; |
120
|
|
|
|
|
|
|
$ch = shift( @{$chars} ); |
121
|
|
|
|
|
|
|
my $key = "$begin_ch-$ch"; |
122
|
|
|
|
|
|
|
if ( defined( $parsed_range_patterns{$key} ) ) { |
123
|
|
|
|
|
|
|
push( @tmp, @{ $parsed_range_patterns{$key} } ); |
124
|
|
|
|
|
|
|
} |
125
|
|
|
|
|
|
|
else { |
126
|
|
|
|
|
|
|
my @chs; |
127
|
|
|
|
|
|
|
for my $n ( ( ord($begin_ch) + 1 ) .. ord($ch) ) { |
128
|
|
|
|
|
|
|
push @chs, chr($n); |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
$parsed_range_patterns{$key} = \@chs; |
131
|
|
|
|
|
|
|
push @tmp, @chs; |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
else { |
135
|
|
|
|
|
|
|
carp "'$ch' will be treated literally inside []" |
136
|
|
|
|
|
|
|
if ( $ch =~ /\W/ ); |
137
|
|
|
|
|
|
|
push( @tmp, $ch ); |
138
|
|
|
|
|
|
|
} |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
croak 'unmatched []' if ( $ch ne ']' ); |
141
|
|
|
|
|
|
|
push( @{$string}, \@tmp ); |
142
|
|
|
|
|
|
|
}, |
143
|
|
|
|
|
|
|
'*' => sub { |
144
|
|
|
|
|
|
|
my ( $self, $ch, $chars, $string ) = @_; |
145
|
|
|
|
|
|
|
unshift( @{$chars}, split( //, '{0,}' ) ); |
146
|
|
|
|
|
|
|
}, |
147
|
|
|
|
|
|
|
'+' => sub { |
148
|
|
|
|
|
|
|
my ( $self, $ch, $chars, $string ) = @_; |
149
|
|
|
|
|
|
|
unshift( @{$chars}, split( //, '{1,}' ) ); |
150
|
|
|
|
|
|
|
}, |
151
|
|
|
|
|
|
|
'?' => sub { |
152
|
|
|
|
|
|
|
my ( $self, $ch, $chars, $string ) = @_; |
153
|
|
|
|
|
|
|
unshift( @{$chars}, split( //, '{0,1}' ) ); |
154
|
|
|
|
|
|
|
}, |
155
|
|
|
|
|
|
|
'{' => sub { |
156
|
|
|
|
|
|
|
my ( $self, $ch, $chars, $string ) = @_; |
157
|
|
|
|
|
|
|
my $closed; |
158
|
|
|
|
|
|
|
CLOSED: |
159
|
|
|
|
|
|
|
for my $c ( @{$chars} ) { |
160
|
|
|
|
|
|
|
if ( $c eq '}' ) { |
161
|
|
|
|
|
|
|
$closed = 1; |
162
|
|
|
|
|
|
|
last CLOSED; |
163
|
|
|
|
|
|
|
} |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
if ($closed) { |
166
|
|
|
|
|
|
|
my $tmp; |
167
|
|
|
|
|
|
|
while ( defined( $ch = shift( @{$chars} ) ) && ( $ch ne '}' ) ) { |
168
|
|
|
|
|
|
|
croak "'$ch' inside {} not supported" if ( $ch !~ /[\d,]/ ); |
169
|
|
|
|
|
|
|
$tmp .= $ch; |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
if ( $tmp =~ /,/ ) { |
172
|
|
|
|
|
|
|
if ( my ( $min, $max ) = $tmp =~ /^(\d*),(\d*)$/ ) { |
173
|
|
|
|
|
|
|
if ( !length($min) ) { $min = 0 } |
174
|
|
|
|
|
|
|
if ( !length($max) ) { $max = $self->{'_max'} } |
175
|
|
|
|
|
|
|
croak "bad range {$tmp}" if ( $min > $max ); |
176
|
|
|
|
|
|
|
if ( $min == $max ) { |
177
|
|
|
|
|
|
|
$tmp = $min; |
178
|
|
|
|
|
|
|
} |
179
|
|
|
|
|
|
|
else { |
180
|
|
|
|
|
|
|
$tmp = $min + $self->{'_rand'}( $max - $min + 1 ); |
181
|
|
|
|
|
|
|
} |
182
|
|
|
|
|
|
|
} |
183
|
|
|
|
|
|
|
else { |
184
|
|
|
|
|
|
|
croak "malformed range {$tmp}"; |
185
|
|
|
|
|
|
|
} |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
if ($tmp) { |
188
|
|
|
|
|
|
|
my $prev_ch = $string->[-1]; |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
push @{$string}, ( ($prev_ch) x ( $tmp - 1 ) ); |
191
|
|
|
|
|
|
|
} |
192
|
|
|
|
|
|
|
else { |
193
|
|
|
|
|
|
|
pop( @{$string} ); |
194
|
|
|
|
|
|
|
} |
195
|
|
|
|
|
|
|
} |
196
|
|
|
|
|
|
|
else { |
197
|
|
|
|
|
|
|
# { isn't closed, so treat it literally. |
198
|
|
|
|
|
|
|
push( @{$string}, [$ch] ); |
199
|
|
|
|
|
|
|
} |
200
|
|
|
|
|
|
|
}, |
201
|
|
|
|
|
|
|
); |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
# Default rand function |
204
|
|
|
|
|
|
|
sub _rand { |
205
|
584
|
|
|
584
|
|
720
|
my ($max) = @_; |
206
|
584
|
|
|
|
|
1017
|
return int rand $max; |
207
|
|
|
|
|
|
|
} |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
sub new { |
210
|
28
|
|
|
28
|
1
|
484
|
my ( $proto, @args ) = @_; |
211
|
28
|
|
33
|
|
|
111
|
my $class = ref($proto) || $proto; |
212
|
28
|
|
|
|
|
32
|
my $self; |
213
|
28
|
|
|
|
|
145
|
$self = {%old_patterns}; # makes $self refer to a copy of %old_patterns |
214
|
28
|
|
|
|
|
49
|
my %args = (); |
215
|
28
|
100
|
|
|
|
134
|
if (@args) { %args = @args } |
|
1
|
|
|
|
|
3
|
|
216
|
28
|
50
|
|
|
|
68
|
if ( defined( $args{'max'} ) ) { |
217
|
0
|
|
|
|
|
0
|
$self->{'_max'} = $args{'max'}; |
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
else { |
220
|
28
|
|
|
|
|
65
|
$self->{'_max'} = 10; |
221
|
|
|
|
|
|
|
} |
222
|
28
|
100
|
|
|
|
54
|
if ( defined( $args{'rand_gen'} ) ) { |
223
|
1
|
|
|
|
|
2
|
$self->{'_rand'} = $args{'rand_gen'}; |
224
|
|
|
|
|
|
|
} |
225
|
|
|
|
|
|
|
else { |
226
|
27
|
|
|
|
|
47
|
$self->{'_rand'} = \&_rand; |
227
|
|
|
|
|
|
|
} |
228
|
28
|
|
|
|
|
80
|
return bless( $self, $class ); |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
# Returns a random string for each regular expression given as an |
232
|
|
|
|
|
|
|
# argument, or the strings concatenated when used in a scalar context. |
233
|
|
|
|
|
|
|
sub randregex { |
234
|
40
|
|
|
40
|
1
|
5936
|
my $self = shift; |
235
|
40
|
50
|
|
|
|
81
|
croak 'called without a reference' if ( !ref($self) ); |
236
|
|
|
|
|
|
|
|
237
|
40
|
|
|
|
|
52
|
my @strings = (); |
238
|
|
|
|
|
|
|
|
239
|
40
|
|
|
|
|
90
|
while ( defined( my $pattern = shift ) ) { |
240
|
74
|
|
|
|
|
93
|
my $ch; |
241
|
74
|
|
|
|
|
148
|
my @string = (); |
242
|
74
|
|
|
|
|
124
|
my $string = q{}; |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
# Split the characters in the pattern |
245
|
|
|
|
|
|
|
# up into a list for easier parsing. |
246
|
74
|
|
|
|
|
202
|
my @chars = split( //, $pattern ); |
247
|
|
|
|
|
|
|
|
248
|
74
|
|
|
|
|
134
|
while ( defined( $ch = shift(@chars) ) ) { |
249
|
198
|
100
|
|
|
|
376
|
if ( defined( $regch{$ch} ) ) { |
|
|
50
|
|
|
|
|
|
250
|
194
|
|
|
|
|
467
|
$regch{$ch}->( $self, $ch, \@chars, \@string ); |
251
|
|
|
|
|
|
|
} |
252
|
|
|
|
|
|
|
elsif ( $ch =~ /[\$\^\*\(\)\+\{\}\]\|\?]/ ) { |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
# At least some of these probably should have special meaning. |
255
|
0
|
|
|
|
|
0
|
carp "'$ch' not implemented. treating literally."; |
256
|
0
|
|
|
|
|
0
|
push( @string, [$ch] ); |
257
|
|
|
|
|
|
|
} |
258
|
|
|
|
|
|
|
else { |
259
|
4
|
|
|
|
|
13
|
push( @string, [$ch] ); |
260
|
|
|
|
|
|
|
} |
261
|
|
|
|
|
|
|
} |
262
|
|
|
|
|
|
|
|
263
|
74
|
|
|
|
|
108
|
foreach my $ch (@string) { |
264
|
556
|
|
|
|
|
583
|
$string .= $ch->[ $self->{'_rand'}( scalar( @{$ch} ) ) ]; |
|
556
|
|
|
|
|
811
|
|
265
|
|
|
|
|
|
|
} |
266
|
|
|
|
|
|
|
|
267
|
74
|
|
|
|
|
299
|
push( @strings, $string ); |
268
|
|
|
|
|
|
|
} |
269
|
|
|
|
|
|
|
|
270
|
40
|
100
|
|
|
|
174
|
return wantarray ? @strings : join( q{}, @strings ); |
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
# For compatibility with an ancient version, please ignore... |
274
|
|
|
|
|
|
|
sub from_pattern { |
275
|
0
|
|
|
0
|
1
|
0
|
my ( $self, @args ) = @_; |
276
|
0
|
0
|
|
|
|
0
|
croak 'called without a reference' if ( !ref($self) ); |
277
|
|
|
|
|
|
|
|
278
|
0
|
|
|
|
|
0
|
return $self->randpattern(@args); |
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
sub randpattern { |
282
|
9
|
|
|
9
|
1
|
9808
|
my $self = shift; |
283
|
9
|
50
|
|
|
|
36
|
croak 'called without a reference' if ( !ref($self) ); |
284
|
|
|
|
|
|
|
|
285
|
9
|
|
|
|
|
18
|
my @strings = (); |
286
|
|
|
|
|
|
|
|
287
|
9
|
|
|
|
|
21
|
while ( defined( my $pattern = shift ) ) { |
288
|
13
|
|
|
|
|
16
|
my $string = q{}; |
289
|
|
|
|
|
|
|
|
290
|
13
|
|
|
|
|
32
|
for my $ch ( split( //, $pattern ) ) { |
291
|
18
|
50
|
|
|
|
42
|
if ( defined( $self->{$ch} ) ) { |
292
|
|
|
|
|
|
|
$string .= $self->{$ch} |
293
|
18
|
|
|
|
|
25
|
->[ $self->{'_rand'}( scalar( @{ $self->{$ch} } ) ) ]; |
|
18
|
|
|
|
|
37
|
|
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
else { |
296
|
0
|
|
|
|
|
0
|
croak qq(Unknown pattern character "$ch"!); |
297
|
|
|
|
|
|
|
} |
298
|
|
|
|
|
|
|
} |
299
|
13
|
|
|
|
|
42
|
push( @strings, $string ); |
300
|
|
|
|
|
|
|
} |
301
|
|
|
|
|
|
|
|
302
|
9
|
100
|
|
|
|
63
|
return wantarray ? @strings : join( q{}, @strings ); |
303
|
|
|
|
|
|
|
} |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
sub random_regex { |
306
|
20
|
|
|
20
|
1
|
4707
|
my (@args) = @_; |
307
|
20
|
|
|
|
|
53
|
my $foo = String::Random->new; |
308
|
20
|
|
|
|
|
40
|
return $foo->randregex(@args); |
309
|
|
|
|
|
|
|
} |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
sub random_string { |
312
|
1
|
|
|
1
|
1
|
426
|
my ( $pattern, @list ) = @_; |
313
|
|
|
|
|
|
|
|
314
|
1
|
|
|
|
|
3
|
my $foo = String::Random->new; |
315
|
|
|
|
|
|
|
|
316
|
1
|
|
|
|
|
3
|
for my $n ( 0 .. $#list ) { |
317
|
3
|
|
|
|
|
4
|
$foo->{$n} = [ @{ $list[$n] } ]; |
|
3
|
|
|
|
|
12
|
|
318
|
|
|
|
|
|
|
} |
319
|
|
|
|
|
|
|
|
320
|
1
|
|
|
|
|
5
|
return $foo->randpattern($pattern); |
321
|
|
|
|
|
|
|
} |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
1; |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
=pod |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
=encoding UTF-8 |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
=head1 NAME |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
String::Random - Perl module to generate random strings based on a pattern |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
=head1 VERSION |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
version 0.31 |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
=head1 SYNOPSIS |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
use String::Random; |
340
|
|
|
|
|
|
|
my $string_gen = String::Random->new; |
341
|
|
|
|
|
|
|
print $string_gen->randregex('\d\d\d'); # Prints 3 random digits |
342
|
|
|
|
|
|
|
# Prints 3 random printable characters |
343
|
|
|
|
|
|
|
print $string_gen->randpattern("..."); |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
I |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
use String::Random qw(random_regex random_string); |
348
|
|
|
|
|
|
|
print random_regex('\d\d\d'); # Also prints 3 random digits |
349
|
|
|
|
|
|
|
print random_string("..."); # Also prints 3 random printable characters |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
=head1 DESCRIPTION |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
This module makes it trivial to generate random strings. |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
As an example, let's say you are writing a script that needs to generate a |
356
|
|
|
|
|
|
|
random password for a user. The relevant code might look something like |
357
|
|
|
|
|
|
|
this: |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
use String::Random; |
360
|
|
|
|
|
|
|
my $pass = String::Random->new; |
361
|
|
|
|
|
|
|
print "Your password is ", $pass->randpattern("CCcc!ccn"), "\n"; |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
This would output something like this: |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
Your password is UDwp$tj5 |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
B: currently, C defaults to Perl's built-in predictable |
368
|
|
|
|
|
|
|
random number generator so the passwords generated by it are insecure. See the |
369
|
|
|
|
|
|
|
C option to C constructor to specify a more secure |
370
|
|
|
|
|
|
|
random number generator. There is no equivalent to this in the procedural |
371
|
|
|
|
|
|
|
interface, you must use the object-oriented interface to get this |
372
|
|
|
|
|
|
|
functionality. |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
If you are more comfortable dealing with regular expressions, the following |
375
|
|
|
|
|
|
|
code would have a similar result: |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
use String::Random; |
378
|
|
|
|
|
|
|
my $pass = String::Random->new; |
379
|
|
|
|
|
|
|
print "Your password is ", |
380
|
|
|
|
|
|
|
$pass->randregex('[A-Z]{2}[a-z]{2}.[a-z]{2}\d'), "\n"; |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
=head2 Patterns |
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
The pre-defined patterns (for use with C and C) |
385
|
|
|
|
|
|
|
are as follows: |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
c Any Latin lowercase character [a-z] |
388
|
|
|
|
|
|
|
C Any Latin uppercase character [A-Z] |
389
|
|
|
|
|
|
|
n Any digit [0-9] |
390
|
|
|
|
|
|
|
! A punctuation character [~`!@$%^&*()-_+={}[]|\:;"'.<>?/#,] |
391
|
|
|
|
|
|
|
. Any of the above |
392
|
|
|
|
|
|
|
s A "salt" character [A-Za-z0-9./] |
393
|
|
|
|
|
|
|
b Any binary data |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
These can be modified, but if you need a different pattern it is better to |
396
|
|
|
|
|
|
|
create another pattern, possibly using one of the pre-defined as a base. |
397
|
|
|
|
|
|
|
For example, if you wanted a pattern C that contained all upper and lower |
398
|
|
|
|
|
|
|
case letters (C<[A-Za-z]>), the following would work: |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
my $gen = String::Random->new; |
401
|
|
|
|
|
|
|
$gen->{'A'} = [ 'A'..'Z', 'a'..'z' ]; |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
I |
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
my $gen = String::Random->new; |
406
|
|
|
|
|
|
|
$gen->{'A'} = [ @{$gen->{'C'}}, @{$gen->{'c'}} ]; |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
The random_string function, described below, has an alternative interface |
409
|
|
|
|
|
|
|
for adding patterns. |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
=head2 Methods |
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
=over 8 |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
=item new |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
=item new max =E I |
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
=item new rand_gen =E I |
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
Create a new String::Random object. |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
Optionally a parameter C can be included to specify the maximum number |
424
|
|
|
|
|
|
|
of characters to return for C<*> and other regular expression patterns that |
425
|
|
|
|
|
|
|
do not return a fixed number of characters. |
426
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
Optionally a parameter C can be included to specify a subroutine |
428
|
|
|
|
|
|
|
coderef for generating the random numbers used in this module. The coderef |
429
|
|
|
|
|
|
|
must accept one argument C and return an integer between 0 and C. |
430
|
|
|
|
|
|
|
The default rand_gen coderef is |
431
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
sub { |
433
|
|
|
|
|
|
|
my ($max) = @_; |
434
|
|
|
|
|
|
|
return int rand $max; |
435
|
|
|
|
|
|
|
} |
436
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
=item randpattern LIST |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
The randpattern method returns a random string based on the concatenation |
440
|
|
|
|
|
|
|
of all the pattern strings in the list. |
441
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
It will return a list of random strings corresponding to the pattern |
443
|
|
|
|
|
|
|
strings when used in list context. |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
=item randregex LIST |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
The randregex method returns a random string that will match the regular |
448
|
|
|
|
|
|
|
expression passed in the list argument. |
449
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
Please note that the arguments to randregex are not real regular |
451
|
|
|
|
|
|
|
expressions. Only a small subset of regular expression syntax is actually |
452
|
|
|
|
|
|
|
supported. So far, the following regular expression elements are |
453
|
|
|
|
|
|
|
supported: |
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
\w Alphanumeric + "_". |
456
|
|
|
|
|
|
|
\d Digits. |
457
|
|
|
|
|
|
|
\W Printable characters other than those in \w. |
458
|
|
|
|
|
|
|
\D Printable characters other than those in \d. |
459
|
|
|
|
|
|
|
. Printable characters. |
460
|
|
|
|
|
|
|
[] Character classes. |
461
|
|
|
|
|
|
|
{} Repetition. |
462
|
|
|
|
|
|
|
* Same as {0,}. |
463
|
|
|
|
|
|
|
? Same as {0,1}. |
464
|
|
|
|
|
|
|
+ Same as {1,}. |
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
Regular expression support is still somewhat incomplete. Currently special |
467
|
|
|
|
|
|
|
characters inside [] are not supported (with the exception of "-" to denote |
468
|
|
|
|
|
|
|
ranges of characters). The parser doesn't care for spaces in the "regular |
469
|
|
|
|
|
|
|
expression" either. |
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
=item from_pattern |
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
B - for compatibility with an old version. B |
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
=back |
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
=head2 Functions |
478
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
=over 8 |
480
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
=item random_string PATTERN,LIST |
482
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
=item random_string PATTERN |
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
When called with a single scalar argument, random_string returns a random |
486
|
|
|
|
|
|
|
string using that scalar as a pattern. Optionally, references to lists |
487
|
|
|
|
|
|
|
containing other patterns can be passed to the function. Those lists will |
488
|
|
|
|
|
|
|
be used for 0 through 9 in the pattern (meaning the maximum number of lists |
489
|
|
|
|
|
|
|
that can be passed is 10). For example, the following code: |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
print random_string("0101", |
492
|
|
|
|
|
|
|
["a", "b", "c"], |
493
|
|
|
|
|
|
|
["d", "e", "f"]), "\n"; |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
would print something like this: |
496
|
|
|
|
|
|
|
|
497
|
|
|
|
|
|
|
cebd |
498
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
=item random_regex REGEX_IN_STRING |
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
Prints a string for the regular expression given as the string. See the |
502
|
|
|
|
|
|
|
synposis for example. |
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
=back |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
=head1 BUGS |
507
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
This is Bug Free™ code. (At least until somebody finds one…) |
509
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
Please report bugs here: |
511
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
L . |
513
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
=head1 AUTHOR |
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
Original Author: Steven Pritchard C<< steve@silug.org >> |
517
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
Now maintained by: Shlomi Fish ( L ). |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
=head1 LICENSE |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
523
|
|
|
|
|
|
|
under the same terms as Perl itself. |
524
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
=head1 SEE ALSO |
526
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
perl(1). |
528
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
=for :stopwords cpan testmatrix url bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan |
530
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
=head1 SUPPORT |
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
=head2 Websites |
534
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
The following websites have more information about this module, and may be of help to you. As always, |
536
|
|
|
|
|
|
|
in addition to those websites please use your favorite search engine to discover more resources. |
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
=over 4 |
539
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
=item * |
541
|
|
|
|
|
|
|
|
542
|
|
|
|
|
|
|
MetaCPAN |
543
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
A modern, open-source CPAN search engine, useful to view POD in HTML format. |
545
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
L |
547
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
=item * |
549
|
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
RT: CPAN's Bug Tracker |
551
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
The RT ( Request Tracker ) website is the default bug/issue tracking system for CPAN. |
553
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
L |
555
|
|
|
|
|
|
|
|
556
|
|
|
|
|
|
|
=item * |
557
|
|
|
|
|
|
|
|
558
|
|
|
|
|
|
|
CPANTS |
559
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
The CPANTS is a website that analyzes the Kwalitee ( code metrics ) of a distribution. |
561
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
L |
563
|
|
|
|
|
|
|
|
564
|
|
|
|
|
|
|
=item * |
565
|
|
|
|
|
|
|
|
566
|
|
|
|
|
|
|
CPAN Testers |
567
|
|
|
|
|
|
|
|
568
|
|
|
|
|
|
|
The CPAN Testers is a network of smoke testers who run automated tests on uploaded CPAN distributions. |
569
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
L |
571
|
|
|
|
|
|
|
|
572
|
|
|
|
|
|
|
=item * |
573
|
|
|
|
|
|
|
|
574
|
|
|
|
|
|
|
CPAN Testers Matrix |
575
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
The CPAN Testers Matrix is a website that provides a visual overview of the test results for a distribution on various Perls/platforms. |
577
|
|
|
|
|
|
|
|
578
|
|
|
|
|
|
|
L |
579
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
=item * |
581
|
|
|
|
|
|
|
|
582
|
|
|
|
|
|
|
CPAN Testers Dependencies |
583
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
The CPAN Testers Dependencies is a website that shows a chart of the test results of all dependencies for a distribution. |
585
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
L |
587
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
=back |
589
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
=head2 Bugs / Feature Requests |
591
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
Please report any bugs or feature requests by email to C, or through |
593
|
|
|
|
|
|
|
the web interface at L. You will be automatically notified of any |
594
|
|
|
|
|
|
|
progress on the request by the system. |
595
|
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
=head2 Source Code |
597
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
The code is open to the world, and available for you to hack on. Please feel free to browse it and play |
599
|
|
|
|
|
|
|
with it, or whatever. If you want to contribute patches, please send me a diff or prod me to pull |
600
|
|
|
|
|
|
|
from your repository :) |
601
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
L |
603
|
|
|
|
|
|
|
|
604
|
|
|
|
|
|
|
git clone http://github.com/shlomif/String-Random |
605
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
=head1 AUTHOR |
607
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
Shlomi Fish |
609
|
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
=head1 BUGS |
611
|
|
|
|
|
|
|
|
612
|
|
|
|
|
|
|
Please report any bugs or feature requests on the bugtracker website |
613
|
|
|
|
|
|
|
L |
614
|
|
|
|
|
|
|
|
615
|
|
|
|
|
|
|
When submitting a bug or request, please include a test-file or a |
616
|
|
|
|
|
|
|
patch to an existing test-file that illustrates the bug or desired |
617
|
|
|
|
|
|
|
feature. |
618
|
|
|
|
|
|
|
|
619
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
620
|
|
|
|
|
|
|
|
621
|
|
|
|
|
|
|
This software is copyright (c) 2020 by Shlomi Fish. |
622
|
|
|
|
|
|
|
|
623
|
|
|
|
|
|
|
This is free software; you can redistribute it and/or modify it under |
624
|
|
|
|
|
|
|
the same terms as the Perl 5 programming language system itself. |
625
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
=cut |
627
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
__END__ |