it-swarm-tr.com

Ruby'de rastgele bir dize oluşturma

Şu anda "A" .. "Z" için 8 karakterli rasgele rasgele bir büyük harf dize oluşturuyorum:

value = ""; 8.times{value  << (65 + Rand(25)).chr}

ama temiz görünmüyor ve tek bir ifade olmadığı için argüman olarak geçilemiyor. "A" .. "z" artı "A" .. "Z" harflerini içeren karışık bir dize almak için şunu değiştirdim:

value = ""; 8.times{value << ((Rand(2)==1?65:97) + Rand(25)).chr}

ama çöp gibi görünüyor.

Daha iyi bir metodu olan var mı?

702
Jeff
(0...8).map { (65 + Rand(26)).chr }.join

Golf oynamak için çok zaman harcıyorum.

(0...50).map { ('a'..'z').to_a[Rand(26)] }.join

Ve daha da kafa karıştırıcı, ancak daha esnek ve daha az döngü harcayan sonuncusu:

o = [('a'..'z'), ('A'..'Z')].map(&:to_a).flatten
string = (0...50).map { o[Rand(o.length)] }.join
908
Kent Fredric

Neden SecureRandom kullanmıyorsunuz?

require 'securerandom'
random_string = SecureRandom.hex

# outputs: 5b5cd0da3121fc53b4bc84d0c8af2e81 (i.e. 32 chars of 0..9, a..f)

SecureRandom ayrıca şu yöntemlere de sahiptir:

  • base64
  • random_bytes
  • rANDOM_NUMBER

bakınız: http://Ruby-doc.org/stdlib-1.9.2/libdoc/securerandom/rdoc/SecureRandom.html

754

Bunu garantili maksimum uzunluğa sahip rastgele URL dostu dizeler oluşturmak için kullanıyorum:

Rand(36**length).to_s(36)

Küçük harf a-z ve 0-9 rasgele dizeleri oluşturur. Çok özelleştirilebilir değil ama kısa ve temiz.

236

Bu çözüm, aktivasyon kodları için kolayca okunabilen bir karakter dizisi oluşturur; İnsanların 8'i B, 1'i I, 0'ı O, L'yi 1'i vb. İle karıştırmak istemedim.

# 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
165
ImNotQuiteJack

Diğerleri de benzer bir şeyden bahsetti, ancak bu URL güvenli işlevini kullanıyor.

require 'securerandom'
p SecureRandom.urlsafe_base64(5) #=> "UtM7aa8"
p SecureRandom.urlsafe_base64 #=> "UZLdOkzop70Ddx-IJR0ABg"
p SecureRandom.urlsafe_base64(nil, true) #=> "i0XQ-7gglIsHGV2_BNPrdQ=="

Sonuç A-Z, a-z, 0-9, “-” ve “_” içerebilir. Dolgu doğruysa “=” da kullanılır.

124
Travis Reeder
[*('A'..'Z')].sample(8).join

Rasgele bir 8 harfli dize oluşturun (örneğin, NVAYXHGR)

([*('A'..'Z'),*('0'..'9')]-%w(0 1 I O)).sample(8).join

Rasgele 8 karakterli bir dize (örneğin, 3PH4SWF2) oluşturun, 0/1/I/O hariç. Yakut 1.9

45
Shai Coleman

Ruby 2.5'ten beri SecureRandom.alphanumeric ile gerçekten kolay:

len = 8
SecureRandom.alphanumeric(len)
=> "larHSsgL"

A-Z, a-z ve 0-9 içeren rasgele dizeler oluşturur ve bu nedenle çoğu kullanımda uygulanabilir olmalıdır. Ve bunlar rastlantısal olarak güvenli bir şekilde üretilir, ki bu da bir fayda olabilir.


Düzenleme: En fazla oyuna sahip olan çözümle karşılaştırmak için bir kıyaslama:

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)

Bu nedenle Rand çözümü SecureRandom zamanının yalnızca 3/4'ünü alır. Gerçekten çok fazla dizge oluşturursanız önemli olabilir, ancak zaman zaman rastgele dizeler yaratırsanız her zaman daha güvenli bir uygulama ile giderim (çünkü daha kolay ve anlaşılır).

34
Markus

Bunu nerede bulduğumu hatırlayamıyorum, ancak bana en iyi ve en az işlem yoğun olarak görünüyor:

def random_string(length=10)
  chars = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ0123456789'
  password = ''
  length.times { password << chars[Rand(chars.size)] }
  password
end
30
Travis Reeder
require 'securerandom'
SecureRandom.urlsafe_base64(9)
27
LENZCOM

Belirtilen uzunlukta bir dize istiyorsanız, şunu kullanın:

require 'securerandom'
randomstring = SecureRandom.hex(n)

Bu, 2n ve 0-9 içeren a-f uzunlukundan rastgele bir dize oluşturur

24

Array.new(n){[*"0".."9"].sample}.join, burada n = 8 durumunda.

Genelleştirilmiş: Array.new(n){[*"A".."Z", *"0".."9"].sample}.join, vb. - this answer

13
gr8scott06
require 'sha1'
srand
seed = "--#{Rand(10000)}--#{Time.now}--"
Digest::SHA1.hexdigest(seed)[0,8]
11
Coren

İşte uzunluğu 8 ile rastgele dize için bir satır basit kod

 random_string = ('0'..'z').to_a.shuffle.first(8).join

Ayrıca uzunluğu 8 olan rastgele şifre için de kullanabilirsiniz.

random_password = ('0'..'z').to_a.shuffle.first(8).join

umarım yardımcı olur ve şaşırtıcı olur.

10
Awais

Yakut 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"
10
Ragmaanir

Unutmayın: Rand bir saldırgan için tahmin edilebilir ve bu nedenle muhtemelen güvensiz. Parola oluşturmak için kesinlikle SecureRandom kullanmalısınız. Böyle bir şey kullanıyorum:

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
8
pencil

İşte uzunluğu 8 rastgele şifre için basit bir kod

Rand_password=('0'..'z').to_a.shuffle.first(8).join

Umarım yardımcı olur.

8
Thaha kp
SecureRandom.base64(15).tr('+/=lIO0', 'pqrsxyz')

Şeytan gelen bir şey

6
Thorpe Obazee

Buraya sentlerimi ekliyorum ...

def random_string(length = 8)
  Rand(32**length).to_s(32)
end
5
pduersteler

String#random 'u Ruby Gem Facets'in facets işlevinden kullanabilirsiniz:

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

temelde bunu yapar:

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
5
Tilo

Kullanmayı sevdiğim başka bir yöntem

 Rand(2**256).to_s(36)[0..7]

Dize uzunluğu hakkında gerçekten paranoyak iseniz ljust ekleyin:

 Rand(2**256).to_s(36).ljust(8,'a')[0..7]
5
user163365

Bence bu güzel bir özsellik, açıklık ve değişiklik kolaylığı dengesi 

characters = ('a'..'z').to_a + ('A'..'Z').to_a
# Prior to 1.9, use .choice, not .sample
(0..8).map{characters.sample}.join

Kolayca değiştirilmiş

Örneğin, rakamlar dahil:

characters = ('a'..'z').to_a + ('A'..'Z').to_a + (0..9).to_a

Büyük harf onaltılık:

characters = ('A'..'F').to_a + (0..9).to_a

Gerçekten etkileyici bir karakter dizisi için:

characters = (32..126).to_a.pack('U*').chars.to_a
5
Nathan Long

Benim favorim (:A..:Z).to_a.shuffle[0,8].join. Karıştırmanın Ruby> 1.9 gerektirdiğini unutmayın.

4
Josh

Bu çözüm dış bağımlılığa ihtiyaç duyuyor, ancak diğerinden daha güzel görünüyor.

  1. Gem faker uygulamasını yükleyin.
  2. Faker::Lorem.characters(10) # => "ang9cbhoa8"
4
asiniy

Verilen:

chars = [*('a'..'z'),*('0'..'9')].flatten

Tekli ifade, bağımsız değişken olarak geçirilebilir, yinelenen karakterlere izin verir:

Array.new(len) { chars.sample }.join
4
Tim James

Benim 2 kuruş:

  def token(length=16)
    chars = [*('A'..'Z'), *('a'..'z'), *(0..9)]
    (0..length).map {chars.sample}.join
  end
3
tybro0103

Ben sadece çoğu kullanım durumunda rastgele belirteçleri oluşturmak için küçük bir mücevher random_token yazın, keyfini çıkarın ~

https://github.com/sibevin/random_token

3
Sibevin Wang
''.tap {|v| 4.times { v << ('a'..'z').to_a.sample} }
3
eric

Geçenlerde 62 karakterden 8 bayt rastgele bir dize üretmek için böyle bir şey yapıyordum. Karakterler 0-9, a-z, A-Z idi. 8 kez döngü oluşturduğu ve diziden rastgele bir değer seçtiği için bir dizisine sahiptim. Bu bir Rails uygulamasının içindeydi.

str = '' 8.times {|i| str << ARRAY_OF_POSSIBLE_VALUES[Rand(SIZE_OF_ARRAY_OF_POSSIBLE_VALUES)] }

İşin garibi, iyi sayıda kopya almam. Şimdi rastgele bu hemen hemen hiç olmamalı. 62 ^ 8 büyük, ancak db içindeki 1200 ya da öylesine kodların çoğunda çok sayıda kopya vardı. Birbirlerinin saat sınırlarında olduklarını fark ettim. Başka bir deyişle, 12:12:23 ve 2:12:22 saatlerinde bir çift görülebilir veya bunun gibi bir şey ... zamanın sorun olup olmadığından emin değil.

Bu kod, bir activerecord nesnesinin oluşturulmasından önceydi. Kayıt oluşturulmadan önce bu kod çalıştırılır ve 'benzersiz' kod oluşturulur. Db içindeki girdiler her zaman güvenilir bir şekilde üretildi, ancak kod (yukarıdaki satırdaki str) çok sık kopyalandı.

Bu satırın 100000 yinelemesini küçük bir gecikmeyle çalıştırmak için bir senaryo hazırladım, böylece saat bazında bir çeşit tekrar deseni görmeyi umarak 3-4 saat sürebilirdi, ancak hiçbir şey görmedim. Bunun Rails uygulamamda neden olduğu hakkında hiçbir fikrim yok.

3
erik

Bir UNIX kullanıyorsanız ve hala Rails olmadan Ruby 1.8 (SecureRandom yok) kullanmanız gerekiyorsa, şunları da kullanabilirsiniz:

random_string = `openssl Rand -base64 24`

Bunun yeni Shell ortaya çıktığını unutmayın, bu çok yavaştır ve yalnızca komut dosyaları için önerilebilir.

2
lzap

Ruby 1.8+ ile çalışan ve hızlı bir başka hile:

>> require "openssl"
>> OpenSSL::Random.random_bytes(20).unpack('H*').join
=> "2f3ff53dd712ba2303a573d9f9a8c1dbc1942d28"

Anladım ki rasgele hex string. Benzer şekilde base64 string ('M *') üretebilmelisiniz.

2
lzap

Radar'ın cevabını en çok seviyorum, bence Biraz böyle Tweak:

CHARS = ('a'..'z').to_a + ('A'..'Z').to_a
def Rand_string(length=8)
  s=''
  length.times{ s << CHARS[Rand(CHARS.length)] }
  s
end
2
webmat

Bu yöntemle isteğe bağlı bir uzunlukta geçebilirsiniz. Varsayılan olarak 6 olarak ayarlanmıştır.

def generate_random_string(length=6)
  string = ""
  chars = ("A".."Z").to_a
  length.times do
    string << chars[Rand(chars.length-1)]
  end
  string
end
2
Ryan Bigg

En iyi atış, 3 aralıktan oluşan rastgele bir dizge için 2 çözüm

(('a'..'z').to_a + ('A'..'Z').to_a + (0..9).to_a).sample(8).join

([*(48..57),*(65..90),*(97..122)]).sample(8).collect(&:chr)*""
2
peter

bunu dene

def Rand_name(len=9)
  ary = [('0'..'9').to_a, ('a'..'z').to_a, ('A'..'Z').to_a]
  name = ''

  len.times do
    name << ary.choice.choice
  end
  name
end

İş parçacığının cevaplarını seviyorum, gerçekten çok yardımcı oldu!, Ama söylersem bunların hiçbiri aylarımı karşılamıyor, belki de Rand () yöntemi. bu bana doğru gelmiyor, çünkü bu konuda Array # seçim yöntemimiz var.

2
Manuel A. Guilamo

İşte başka bir yöntem:

  • Rand () yerine güvenli rasgele sayı üretecini kullanır.
  • URL'lerde ve dosya adlarında kullanılabilir
  • Büyük harf, küçük harf karakter ve sayı içerir
  • Belirsiz karakterleri içermeyen bir seçeneğe sahiptir I0l01

require "securerandom" gerekiyor

def secure_random_string(length = 32, non_ambiguous = false)
  characters = ('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a

  %w{I O l 0 1}.each{ |ambiguous_character| 
    characters.delete ambiguous_character 
  } if non_ambiguous

  (0...length).map{
    characters[ActiveSupport::SecureRandom.random_number(characters.size)]
  }.join
end
2
Evgenii
10.times do 
  alphabet = ('a'..'z').to_a
  string += alpha[Rand(alpha.length)]
end
1
mminski

Bu, birkaç yanıtı temel alır, ancak biraz daha fazla karmaşıklık ekler:

def random_password
  specials = ((32..47).to_a + (58..64).to_a + (91..96).to_a + (123..126).to_a).pack('U*').chars.to_a
  numbers  = (0..9).to_a
  alpha    = ('a'..'z').to_a + ('A'..'Z').to_a
  %w{i I l L 1 O o 0}.each{ |ambiguous_character| 
    alpha.delete ambiguous_character 
  }
  characters = (alpha + specials + numbers)
  password = Random.new.Rand(8..18).times.map{characters.sample}
  password << specials.sample unless password.join =~ Regexp.new(Regexp.escape(specials.join))
  password << numbers.sample  unless password.join =~ Regexp.new(Regexp.escape(numbers.join))
  password.shuffle.join
end

Temelde 8 - 20 karakter uzunluğunda ve en az bir numara ve bir özel karakter içeren bir şifre sağlar.

1
Chris Bloom

Bu cihaz için secure_validatable kullanabilirsiniz.

(0 ... 8) .map {([65, 97]. Örnek + Rand (26)). Chr} .Push (Rand (99)) birleştir

1
shiva kumar

İşte @Travis R cevabının bir iyileştirmesi:

 def random_string(length=5)
    chars = 'abdefghjkmnpqrstuvwxyzABDEFGHJKLMNPQRSTUVWXYZ'
    numbers = '0123456789'
    random_s = ''
    (length/2).times { random_s << numbers[Rand(numbers.size)] }
    (length - random_s.length).times { random_s << chars[Rand(chars.size)] }
    random_s.split('').shuffle.join
  end

@Travis R'de cevap karakterleri ve sayıları beraberdi, bu yüzden random_string bazen sadece sayıları ya da sadece karakterleri geri getirebilirdi. Bu gelişme ile random_string 'un en az yarısı karakter olacak ve geri kalan sayılar olacaktır. Sadece rakam ve karakter içeren rastgele bir dizgeye ihtiyacınız olursa

0
Lucas Andrade

İlkini bir ifadeye dönüştürmek için:

(0...8).collect { |n| value  << (65 + Rand(25)).chr }.join()
0
Kevin Conner

En kolay yol string_pattern gem https://github.com/MarioRuiz/string_pattern kullanmaktır.

Örneğin 36 rastgele harf oluşturmak için:

 require 'string_pattern'
 puts '36:L'.gen

Ayrıca normal ifadeler kullanabilirsiniz

 require 'string_pattern'
 puts /[a-zA-Z]{36}/.gen
0
Mario Ruiz

Gerekirse boş bir dize veya ön düzeltme oluşturun:

myStr = "OID-"

Dizeyi rastgele sayılarla doldurmak için bu kodu kullanın:

begin; n = ((Rand * 43) + 47).ceil; myStr << n.chr if !(58..64).include?(n); end while(myStr.length < 12)

Notlar:

(Rand * 43) + 47).ceil

48-91 arasında rasgele sayılar üretecektir (0,1,2..Y, Z)

!(58..64).include?(n)

Özel karakterleri atlamak için kullanılır (onları dahil etmek istemediğim için)

while(myStr.length < 12)

Önek dahil olmak üzere toplam 12 karakter uzunluğunda dize oluşturur.

Örnek çıktı:

"OID-XZ2J32XM"
0
Ghazi
a='';8.times{a<<[*'a'..'z'].sample};p a

veya

8.times.collect{[*'a'..'z'].sample}.join
0
Michael Kingski

Bunu kodumuzda kullanıyorduk:

class String

  def self.random(length=10)
    ('a'..'z').sort_by {Rand}[0,length].join
  end

end

Desteklenen maksimum uzunluk 25'tir (biz yine de yalnızca varsayılanla kullanıyoruz, bu nedenle bir sorun olmadı).

Birisi, rahatsız edici kelimeler oluşturmaktan tamamen kaçınmak istiyorsanız 'a' .. 'z' nin yetersiz olduğunu belirtti. Sahip olduğumuz fikirlerden biri ünlüleri kaldırmaktı, ama yine de WTFBBQ vb.

0
Carlos Villela
`pwgen 8 1`.chomp
0
Nathan L Smith

İşte esnek ve dup izin veren bir çözüm:

class String
  # generate a random string of length n using current string as the source of characters
  def random(n)
    return "" if n <= 0
    (chars * (n / length + 1)).shuffle[0..n-1].join  
  end
end

Örnek:

"ATCG".random(8) => "CGTGAAGA"

Belirli bir karakterin daha sık görünmesine de izin verebilirsiniz:

"AAAAATCG".random(10) => "CTGAAAAAGC"

Açıklama: Yukarıdaki yöntem, verilen bir dizgenin karakterlerini alır ve yeterince büyük bir dizi oluşturur. Daha sonra karıştırır, ilk n maddeyi alır, sonra onlara katılır.

0
Abdo
Array.new(8).inject(""){|r|r<<('0'..'z').to_a.shuffle[0]}  # 57
(1..8).inject(""){|r|r<<('0'..'z').to_a.shuffle[0]}        # 51
e="";8.times{e<<('0'..'z').to_a.shuffle[0]};e              # 45
(1..8).map{('0'..'z').to_a.shuffle[0]}.join                # 43
(1..8).map{Rand(49..122).chr}.join                         # 34
0
Automatico

'SafeRandom' Gem kullanın GithubLink

Rails2, Rails 3, Rails 4, Rails 5 uyumlu için rasgele değerler üretmenin en kolay yolunu sağlayacaktır. 

0
Rubyist