Cómo generar una cadena aleatoria en Ruby
Actualmente estoy generando una cadena pseudo-aleatoria en mayúsculas 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 declaración. Para obtener una cadena de mayúsculas y minúsculas "a".. "z" más "A".. "Z", lo cambié a:
value = ""; 8.times{value << ((rand(2)==1?65:97) + rand(25)).chr}
Pero parece basura.
¿alguien tiene un método mejor?
30 answers
(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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-09 10:56:00
¿Por qué no usar SecureRandom?
require 'securerandom'
random_string = SecureRandom.hex
# outputs: 5b5cd0da3121fc53b4bc84d0c8af2e81 (i.e. 32 chars of 0..9, a..f)
SecureRandom también tiene métodos para:
- base64
- random_bytes
- random_number
Véase: http://ruby-doc.org/stdlib-1.9.2/libdoc/securerandom/rdoc/SecureRandom.html
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-04 20:07:47
Uso esto para generar cadenas aleatorias amigables con URL con una longitud máxima garantizada:
rand(36**length).to_s(36)
Genera cadenas aleatorias de a-z minúsculas y 0-9. No es muy personalizable, pero es corto y limpio.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-04 08:37:57
Esta solución genera una cadena de caracteres fácilmente legibles para los códigos de activación; no quería que la gente confundiera 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 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-25 00:32:31
Otros han mencionado algo similar, pero esto usa la función URL safe.
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 a-Z, a-z, 0-9, "-" y "_". "="también se usa si el relleno es verdadero.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-16 19:40:12
[*('A'..'Z')].sample(8).join
Generar una cadena aleatoria de 8 letras (por ejemplo, NVAYXHGR)
([*('A'..'Z'),*('0'..'9')]-%w(0 1 I O)).sample(8).join
Generar una cadena aleatoria de 8 caracteres (por ejemplo, 3PH4SWF2), excluye 0/1 / I / O. Ruby 1.9
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-22 11:58:53
No puedo recordar dónde encontré esto, pero me parece el mejor y el menos intensivo proceso:
def random_string(length=10)
chars = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ0123456789'
password = ''
length.times { password << chars[rand(chars.size)] }
password
end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-24 22:41:44
require 'securerandom'
SecureRandom.urlsafe_base64(9)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-13 00:34:57
Desde ruby 2.5 realmente fácil con SecureRandom.alphanumeric
:
len = 8
SecureRandom.alphanumeric(len)
=> "larHSsgL"
Genera cadenas aleatorias que contienen A-Z, a-z y 0-9 y, por lo tanto, debería ser aplicable en la mayoría de los casos de uso. Y se generan aleatoriamente seguros, 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 positivos:
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)
Así que la solución rand
solo toma alrededor de 3/4 del tiempo de SecureRandom
. Podría importar si generas realmente un montón de cadenas, pero si simplemente cree alguna 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).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-30 12:39:47
Si desea una cadena de longitud especificada, use:
require 'securerandom'
randomstring = SecureRandom.hex(n)
Generará una cadena aleatoria de longitud 2n
que contiene 0-9
y a-f
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-15 09:28:29
Array.new(n){[*"0".."9"].sample}.join
,
donde n = 8 en su caso.
Generalizado: Array.new(n){[*"A".."Z", *"0".."9"].sample}.join
, etc. - de esta respuesta
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:54:59
require 'sha1'
srand
seed = "--#{rand(10000)}--#{Time.now}--"
Digest::SHA1.hexdigest(seed)[0,8]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-17 22:40:34
Aquí hay un código simple de línea para cadena aleatoria con longitud 8
random_string = ('0'..'z').to_a.shuffle.first(8).join
También puede usarlo para contraseñas aleatorias que tengan una longitud 8
random_password = ('0'..'z').to_a.shuffle.first(8).join
Espero que ayude y sorprendente.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-19 06:12:15
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"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-13 15:04:26
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.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-15 06:51:24
Tenga en cuenta: 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-30 14:30:32
SecureRandom.base64(15).tr('+/=lIO0', 'pqrsxyz')
Algo de Devise
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-19 00:25:43
Otro método que me gusta usar
rand(2**256).to_s(36)[0..7]
Agregue ljust si usted es realmente paranoico acerca de la longitud correcta de la cadena:
rand(2**256).to_s(36).ljust(8,'a')[0..7]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-08 23:17:16
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 modificable
Por ejemplo, incluyendo 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-23 20:34:38
Solo sumando mis centavos aquí...
def random_string(length = 8)
rand(32**length).to_s(32)
end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-16 02:22:00
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-22 22:53:52
Mi favorito es (:A..:Z).to_a.shuffle[0,8].join
. Tenga en cuenta que shuffle requiere Ruby > 1.9.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-28 18:18:17
Esta solución necesita dependencia externa, pero parece más bonita que otra.
- Instalar gem faker
Faker::Lorem.characters(10) # => "ang9cbhoa8"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-18 16:12:49
Dado:
chars = [*('a'..'z'),*('0'..'9')].flatten
Expresión única, se puede pasar como argumento, permite caracteres duplicados:
Array.new(len) { chars.sample }.join
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-31 09:56:55
''.tap {|v| 4.times { v << ('a'..'z').to_a.sample} }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-26 18:03:50
Mis 2 centavos:
def token(length=16)
chars = [*('A'..'Z'), *('a'..'z'), *(0..9)]
(0..length).map {chars.sample}.join
end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-03 15:49:14
Acabo de escribir una pequeña gema random_token
para generar tokens aleatorios para la mayoría de los casos de uso, enjoy ~
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-03 04:01:18
Con este método se puede pasar una longitud abitraria. Se establece como valor predeterminado 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-18 00:53:41
Me gusta más la respuesta de Radar, hasta ahora, creo. Me gustaría ajustar 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-18 02:35:00
Estaba haciendo algo como esto recientemente para generar una cadena aleatoria de 8 bytes a partir de 62 caracteres. Los caracteres eran 0-9, a-z, A-Z. Tenía una matriz de ellos como looping 8 veces y eligiendo un valor aleatorio de la matriz. Esto estaba dentro de una aplicación rails.
str = ''
8.times {|i| str << ARRAY_OF_POSSIBLE_VALUES[rand(SIZE_OF_ARRAY_OF_POSSIBLE_VALUES)] }
Lo raro es que tengo un buen número de duplicados. Ahora, al azar, esto casi nunca debería suceder. 62^8 es enorme, pero de 1200 más o menos códigos en la base de datos que tenía un buen número de duplicados. Me di cuenta ellos pasando en los límites de hora uno de otro. En otras palabras, podría ver una dupla a las 12:12:23 y 2: 12: 22 o algo así...no estoy seguro de si el tiempo es el problema o no.
Este código estaba en la creación anterior de un objeto activerecord. Antes de que se creara el registro, este código se ejecutaría y generaría el código 'único'. Las entradas en la base de datos siempre se producían de forma fiable, pero el código (str en la línea anterior) se duplicaba con demasiada frecuencia.
He creado un script para ejecutar 100000 iteraciones de esta línea anterior con un pequeño retraso por lo que tomaría 3-4 horas con la esperanza de ver algún tipo de patrón de repetición sobre una base horaria, pero no vio nada. No tengo ni idea de por qué estaba pasando esto en mi aplicación rails.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-07 20:16:09