Cómo generar una cadena aleatoria en Ruby

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:

  • base64
  • random_bytes
  • número aleatorio

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 

Fácilmente modificado

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 :

https://github.com/rubyworks/facets/blob/126a619fd766bc45588cac18d09c4f1927538e33/lib/core/facets/string/random.rb

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.

  1. Instalar gem faker
  2. 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 ~

https://github.com/sibevin/random_token

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.

    Intereting Posts