可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I\'m currently generating an 8-character pseudo-random uppercase string for \"A\" .. \"Z\":
value = \"\"; 8.times{value << (65 + rand(25)).chr}
but it doesn\'t look clean, and it can\'t be passed as an argument since it isn\'t a single statement. To get a mixed-case string \"a\" .. \"z\" plus \"A\" .. \"Z\", I changed it to:
value = \"\"; 8.times{value << ((rand(2)==1?65:97) + rand(25)).chr}
but it looks like trash.
Does anyone have a better method?
回答1:
(0...8).map { (65 + rand(26)).chr }.join
I spend too much time golfing.
(0...50).map { (\'a\'..\'z\').to_a[rand(26)] }.join
And a last one that\'s even more confusing, but more flexible and wastes fewer cycles:
o = [(\'a\'..\'z\'), (\'A\'..\'Z\')].map(&:to_a).flatten
string = (0...50).map { o[rand(o.length)] }.join
回答2:
Why not use SecureRandom?
require \'securerandom\'
random_string = SecureRandom.hex
# outputs: 5b5cd0da3121fc53b4bc84d0c8af2e81 (i.e. 32 chars of 0..9, a..f)
SecureRandom also has methods for:
- base64
- random_bytes
- random_number
see: http://ruby-doc.org/stdlib-1.9.2/libdoc/securerandom/rdoc/SecureRandom.html
回答3:
I use this for generating random URL friendly strings with a guaranteed maximum length:
rand(36**length).to_s(36)
It generates random strings of lowercase a-z and 0-9. It\'s not very customizable but it\'s short and clean.
回答4:
This solution generates a string of easily readable characters for activation codes; I didn\'t want people confusing 8 with B, 1 with I, 0 with O, L with 1, etc.
# Generates a random string from a set of easily readable characters
def generate_activation_code(size = 6)
charset = %w{ 2 3 4 6 7 9 A C D E F G H J K M N P Q R T V W X Y Z}
(0...size).map{ charset.to_a[rand(charset.size)] }.join
end
回答5:
Others have mentioned something similar, but this uses the URL safe function.
require \'securerandom\'
p SecureRandom.urlsafe_base64(5) #=> \"UtM7aa8\"
p SecureRandom.urlsafe_base64 #=> \"UZLdOkzop70Ddx-IJR0ABg\"
p SecureRandom.urlsafe_base64(nil, true) #=> \"i0XQ-7gglIsHGV2_BNPrdQ==\"
The result may contain A-Z, a-z, 0-9, “-” and “_”. “=” is also used if padding is true.
回答6:
[*(\'A\'..\'Z\')].sample(8).join
Generate a random 8 letter string (e.g. NVAYXHGR)
([*(\'A\'..\'Z\'),*(\'0\'..\'9\')]-%w(0 1 I O)).sample(8).join
Generate a random 8 character string (e.g. 3PH4SWF2), excludes 0/1/I/O. Ruby 1.9
回答7:
I can\'t remember where I found this, but it seems like the best and the least process intensive to me:
def random_string(length=10)
chars = \'abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ0123456789\'
password = \'\'
length.times { password << chars[rand(chars.size)] }
password
end
回答8:
Since ruby 2.5 really easy with SecureRandom.alphanumeric
:
len = 8
SecureRandom.alphanumeric(len)
=> \"larHSsgL\"
Generates random strings containing A-Z, a-z and 0-9 and therefore should be applicable in most use cases. And they are generated randomly secure, which might be a benefit, too.
Edit: A benchmark to compare it with the solution having the most upvotes:
require \'benchmark\'
require \'securerandom\'
len = 10
n = 100_000
Benchmark.bm(12) do |x|
x.report(\'SecureRandom\') { n.times { SecureRandom.alphanumeric(len) } }
x.report(\'rand\') do
o = [(\'a\'..\'z\'), (\'A\'..\'Z\'), (0..9)].map(&:to_a).flatten
n.times { (0...len).map { o[rand(o.length)] }.join }
end
end
user system total real
SecureRandom 0.429442 0.002746 0.432188 ( 0.432705)
rand 0.306650 0.000716 0.307366 ( 0.307745)
So the rand
solution only takes about 3/4 of the time of SecureRandom
. Might matter if you generate really a lot of strings, but if you just create some random string from time to time I\'d always go with the more secure implementation (since it is also easier to call and more explicit).
回答9:
require \'securerandom\'
SecureRandom.urlsafe_base64(9)
回答10:
If you want a string of specified length, use:
require \'securerandom\'
randomstring = SecureRandom.hex(n)
It will generate a random string of length 2n
containing 0-9
and a-f
回答11:
Array.new(n){[*\"0\"..\"9\"].sample}.join
,
where n=8 in your case.
Generalized: Array.new(n){[*\"A\"..\"Z\", *\"0\"..\"9\"].sample}.join
, etc. - from this answer
回答12:
require \'sha1\'
srand
seed = \"--#{rand(10000)}--#{Time.now}--\"
Digest::SHA1.hexdigest(seed)[0,8]
回答13:
Here is one line simple code for random string with length 8
random_string = (\'0\'..\'z\').to_a.shuffle.first(8).join
You can also use it for random password having length 8
random_password = (\'0\'..\'z\').to_a.shuffle.first(8).join
i hope it will help and amazing.
回答14:
Ruby 1.9+:
ALPHABET = (\'a\'..\'z\').to_a
#=> [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\", \"k\", \"l\", \"m\", \"n\", \"o\", \"p\", \"q\", \"r\", \"s\", \"t\", \"u\", \"v\", \"w\", \"x\", \"y\", \"z\"]
10.times.map { ALPHABET.sample }.join
#=> \"stkbssowre\"
# or
10.times.inject(\'\') { |s| s + ALPHABET.sample }
#=> \"fdgvacnxhc\"
回答15:
Here is one simple code for random password with lenth 8
rand_password=(\'0\'..\'z\').to_a.shuffle.first(8).join
Hope it will help.
回答16:
Be aware: rand
is predictable for an attacker and therefore probably insecure. You should definitely use SecureRandom if this is for generating passwords. I use something like this:
length = 10
characters = (\'A\'..\'Z\').to_a + (\'a\'..\'z\').to_a + (\'0\'..\'9\').to_a
password = SecureRandom.random_bytes(length).each_char.map do |char|
characters[(char.ord % characters.length)]
end.join
回答17:
SecureRandom.base64(15).tr(\'+/=lIO0\', \'pqrsxyz\')
Something from Devise
回答18:
Another method I like to use
rand(2**256).to_s(36)[0..7]
Add ljust if you are really paranoid about the correct string length:
rand(2**256).to_s(36).ljust(8,\'a\')[0..7]
回答19:
I think this is a nice balance of conciseness, clarity and ease of modification.
characters = (\'a\'..\'z\').to_a + (\'A\'..\'Z\').to_a
# Prior to 1.9, use .choice, not .sample
(0..8).map{characters.sample}.join
Easily modified
For example, including digits:
characters = (\'a\'..\'z\').to_a + (\'A\'..\'Z\').to_a + (0..9).to_a
Uppercase hexadecimal:
characters = (\'A\'..\'F\').to_a + (0..9).to_a
For a truly impressive array of characters:
characters = (32..126).to_a.pack(\'U*\').chars.to_a
回答20:
Just adding my cents here...
def random_string(length = 8)
rand(32**length).to_s(32)
end
回答21:
you can use String#random
from the Facets of Ruby Gem facets
:
https://github.com/rubyworks/facets/blob/126a619fd766bc45588cac18d09c4f1927538e33/lib/core/facets/string/random.rb
it basically does this:
class String
def self.random(len=32, character_set = [\"A\"..\"Z\", \"a\"..\"z\", \"0\"..\"9\"])
characters = character_set.map { |i| i.to_a }.flatten
characters_len = characters.length
(0...len).map{ characters[rand(characters_len)] }.join
end
end
回答22:
My favorite is (:A..:Z).to_a.shuffle[0,8].join
. Note that shuffle requires Ruby > 1.9.
回答23:
This solution needs external dependency, but seems prettier than another.
- Install gem faker
Faker::Lorem.characters(10) # => \"ang9cbhoa8\"
回答24:
Given:
chars = [*(\'a\'..\'z\'),*(\'0\'..\'9\')].flatten
Single expression, can be passed as an argument, allows duplicate characters:
Array.new(len) { chars.sample }.join
回答25:
I was doing something like this recently to generate an 8 byte random string from 62 characters. The characters were 0-9,a-z,A-Z. I had an array of them as was looping 8 times and picking a random value out of the array. This was inside a rails app.
str = \'\'
8.times {|i| str << ARRAY_OF_POSSIBLE_VALUES[rand(SIZE_OF_ARRAY_OF_POSSIBLE_VALUES)] }
The weird thing is that I got good number of duplicates. Now randomly this should pretty much never happen. 62^8 is huge, but out of 1200 or so codes in the db i had a good number of duplicates. I noticed them happening on hour boundaries of each other. In other words I might see a duple at 12:12:23 and 2:12:22 or something like that...not sure if time is the issue or not.
This code was in the before create of an activerecord object. Before the record was created this code would run and generate the \'unique\' code. Entries in the db were always produced reliably, but the code (str in the above line) was being duplicated much too often.
I created a script to run through 100000 iterations of this above line with small delay so it would take 3-4 hours hoping to see some kind of repeat pattern on an hourly basis, but saw nothing. I have no idea why this was happening in my rails app.
回答26:
\'\'.tap {|v| 4.times { v << (\'a\'..\'z\').to_a.sample} }
回答27:
My 2 cents:
def token(length=16)
chars = [*(\'A\'..\'Z\'), *(\'a\'..\'z\'), *(0..9)]
(0..length).map {chars.sample}.join
end
回答28:
I just write a small gem random_token
to generate random tokens for most use case, enjoy ~
https://github.com/sibevin/random_token
回答29:
With this method you can pass in an abitrary length. It\'s set as a default as 6.
def generate_random_string(length=6)
string = \"\"
chars = (\"A\"..\"Z\").to_a
length.times do
string << chars[rand(chars.length-1)]
end
string
end
回答30:
I like Radar\'s answer best, so far, I think. I\'d tweak a bit like this:
CHARS = (\'a\'..\'z\').to_a + (\'A\'..\'Z\').to_a
def rand_string(length=8)
s=\'\'
length.times{ s << CHARS[rand(CHARS.length)] }
s
end