Actualmente estoy generando una cadena mayúscula pseudoaleatoria de 8 caracteres para “A” .. “Z”:
value = ""; 8.times{value << (65 + rand(25)).chr}
pero no se ve limpio, y no se puede pasar como un argumento ya que no es una sola statement. Para obtener una cadena de mayúsculas y minúsculas “a” … “z” más “A” .. “Z”, la cambié a:
value = ""; 8.times{value << ((rand(2)==1?65:97) + rand(25)).chr}
pero parece basura.
¿Alguien tiene un mejor método?
(0...8).map { (65 + rand(26)).chr }.join
Paso demasiado tiempo jugando al golf.
(0...50).map { ('a'..'z').to_a[rand(26)] }.join
Y una última que es aún más confusa, pero más flexible y desperdicia menos ciclos:
o = [('a'..'z'), ('A'..'Z')].map(&:to_a).flatten string = (0...50).map { o[rand(o.length)] }.join
¿Por qué no usar SecureRandom?
require 'securerandom' random_string = SecureRandom.hex # outputs: 5b5cd0da3121fc53b4bc84d0c8af2e81 (ie 32 chars of 0..9, a..f)
SecureRandom también tiene métodos para:
ver: http://ruby-doc.org/stdlib-1.9.2/libdoc/securerandom/rdoc/SecureRandom.html
Utilizo esto para generar cadenas aleatorias de URL aleatorias con una duración máxima garantizada:
rand(36**length).to_s(36)
Genera cadenas aleatorias de az minúsculas y 0-9. No es muy personalizable, pero es corto y limpio.
Esta solución genera una cadena de caracteres fácilmente legibles para los códigos de activación; No quería que las personas confundieran 8 con B, 1 con I, 0 con O, L con 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 ACDEFGHJKMNPQRTVWXYZ} (0...size).map{ charset.to_a[rand(charset.size)] }.join end
Otros han mencionado algo similar, pero esto utiliza la función URL segura.
require 'securerandom' p SecureRandom.urlsafe_base64(5) #=> "UtM7aa8" p SecureRandom.urlsafe_base64 #=> "UZLdOkzop70Ddx-IJR0ABg" p SecureRandom.urlsafe_base64(nil, true) #=> "i0XQ-7gglIsHGV2_BNPrdQ=="
El resultado puede contener AZ, az, 0-9, “-” y “_”. “=” También se usa si el relleno es verdadero.
[*('A'..'Z')].sample(8).join
Generar una cadena aleatoria de 8 letras (p. Ej. NVAYXHGR)
([*('A'..'Z'),*('0'..'9')]-%w(0 1 IO)).sample(8).join
Genere una cadena aleatoria de 8 caracteres (p. Ej., 3PH4SWF2), excluye 0/1 / I / O. Ruby 1.9
No recuerdo dónde encontré esto, pero parece ser el mejor y el menos intenso para mí:
def random_string(length=10) chars = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ0123456789' password = '' length.times { password << chars[rand(chars.size)] } password end
require 'securerandom' SecureRandom.urlsafe_base64(9)
Si quieres una cadena de longitud especificada, utiliza:
require 'securerandom' randomstring = SecureRandom.hex(n)
Generará una cadena aleatoria de longitud 2n
contiene 0-9
y af
Desde ruby 2.5 realmente fácil con SecureRandom.alphanumeric
:
len = 8 SecureRandom.alphanumeric(len) => "larHSsgL"
Genera cadenas aleatorias que contienen AZ, az y 0-9 y, por lo tanto, deberían ser aplicables en la mayoría de los casos de uso. Y se generan de forma aleatoria segura, lo que también podría ser un beneficio.
Editar: un punto de referencia para compararlo con la solución que tiene más votos ascendentes:
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)
Entonces la solución rand
solo toma aproximadamente 3/4 del tiempo de SecureRandom
. Podría ser importante si generas muchas cadenas, pero si simplemente creas una cadena aleatoria de vez en cuando, siempre iría con la implementación más segura (ya que también es más fácil de llamar y más explícita).
Array.new(n){[*"0".."9"].sample}.join
, donde n = 8 en tu caso.
Generalizado: Array.new(n){[*"A".."Z", *"0".."9"].sample}.join
, etc. – a partir de esta respuesta
require 'sha1' srand seed = "--#{rand(10000)}--#{Time.now}--" Digest::SHA1.hexdigest(seed)[0,8]
Aquí hay una línea de código simple para cadena aleatoria con longitud 8
random_string = ('0'..'z').to_a.shuffle.first(8).join
También puede usarla para una contraseña aleatoria con una longitud de 8
random_password = ('0'..'z').to_a.shuffle.first(8).join
espero que ayude y asombroso.
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"
Aquí hay un código simple para la contraseña aleatoria con lenth 8
rand_password=('0'..'z').to_a.shuffle.first(8).join
Espero que ayude
Tenga en cuenta que rand
es predecible para un atacante y, por lo tanto, probablemente inseguro. Definitivamente debe usar SecureRandom si esto es para generar contraseñas. Yo uso algo como esto:
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
SecureRandom.base64(15).tr('+/=lIO0', 'pqrsxyz')
Algo de Devise
Otro método que me gusta usar
rand(2**256).to_s(36)[0..7]
Agrega ljust si eres realmente paranoico con la longitud correcta de la cuerda:
rand(2**256).to_s(36).ljust(8,'a')[0..7]
Creo que este es un buen equilibrio de concisión, claridad y facilidad de modificación.
characters = ('a'..'z').to_a + ('A'..'Z').to_a # Prior to 1.9, use .choice, not .sample (0..8).map{characters.sample}.join
Por ejemplo, incluidos los dígitos:
characters = ('a'..'z').to_a + ('A'..'Z').to_a + (0..9).to_a
Hexadecimal en mayúsculas:
characters = ('A'..'F').to_a + (0..9).to_a
Para una impresionante variedad de personajes:
characters = (32..126).to_a.pack('U*').chars.to_a
Solo agrego mis centavos aquí …
def random_string(length = 8) rand(32**length).to_s(32) end
Puedes usar String#random
de las Facetas de Ruby Gem facets
:
Básicamente hace esto:
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
Mi favorito es (:A..:Z).to_a.shuffle[0,8].join
. Tenga en cuenta que Shuffle requiere Ruby> 1.9.
Esta solución necesita dependencia externa, pero parece más bonita que otra.
Faker::Lorem.characters(10) # => "ang9cbhoa8"
Dado:
chars = [*('a'..'z'),*('0'..'9')].flatten
Una sola expresión, se puede pasar como un argumento, permite caracteres duplicados:
Array.new(len) { chars.sample }.join
''.tap {|v| 4.times { v << ('a'..'z').to_a.sample} }
Mis 2 centavos:
def token(length=16) chars = [*('A'..'Z'), *('a'..'z'), *(0..9)] (0..length).map {chars.sample}.join end
Solo escribo una pequeña joya random_token
para generar tokens aleatorios para la mayoría de los casos de uso, disfruta ~
Con este método puede pasar en una longitud abitrary. Está configurado de manera predeterminada como 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
Me gusta más la respuesta de Radar, hasta ahora, creo. Me gustaría modificar un poco como esto:
CHARS = ('a'..'z').to_a + ('A'..'Z').to_a def rand_string(length=8) s='' length.times{ s << CHARS[rand(CHARS.length)] } s end
Estuve haciendo algo como esto recientemente para generar una cadena aleatoria de 8 bytes de 62 caracteres. Los personajes eran 0-9, az, AZ. Tenía una serie de ellos, como lo hacía 8 veces y seleccionaba un valor aleatorio de la matriz. Esto estaba dentro de una aplicación de Rails.
str = '' 8.times {|i| str << ARRAY_OF_POSSIBLE_VALUES[rand(SIZE_OF_ARRAY_OF_POSSIBLE_VALUES)] }
Lo extraño es que obtuve una buena cantidad de duplicados. Ahora, al azar, esto nunca debería pasar. 62 ^ 8 es enorme, pero de 1200 o más códigos en el DB tenía una buena cantidad de duplicados. Noté que sucedían en límites de horas el uno del otro. En otras palabras, podría ver un duple a las 12:12:23 y 2:12:22 o algo así ... no estoy seguro si el problema es el tiempo o no.
Este código estaba en la creación previa de un objeto activerecord. Antes de que se creara el registro, este código se ejecutaba y generaba el código 'único'. Las entradas en el db siempre se producían de manera confiable, pero el código (str en la línea anterior) se duplicaba con demasiada frecuencia.
Creé una secuencia de comandos para ejecutar 100000 iteraciones de esta línea anterior con un pequeño retraso, por lo que tardaría de 3 a 4 horas con la esperanza de ver algún tipo de patrón de repetición cada hora, pero no vi nada. No tengo idea de por qué esto estaba sucediendo en mi aplicación de Rails.