it-swarm-id.com

Cara menghasilkan string acak di Ruby

Saat ini saya sedang membuat string huruf besar pseudo-acak 8-karakter untuk "A" .. "Z":

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

tapi itu tidak terlihat bersih, dan itu tidak bisa diajukan sebagai argumen karena itu bukan pernyataan tunggal. Untuk mendapatkan string case campuran "a" .. "z" plus "A" .. "Z", saya mengubahnya menjadi:

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

tapi sepertinya sampah.

Adakah yang punya metode yang lebih baik?

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

Saya menghabiskan terlalu banyak waktu bermain golf.

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

Dan yang terakhir bahkan lebih membingungkan, tetapi lebih fleksibel dan membuang lebih sedikit siklus:

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

Mengapa tidak menggunakan SecureRandom?

require 'securerandom'
random_string = SecureRandom.hex

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

SecureRandom juga memiliki metode untuk:

  • base64
  • random_bytes
  • angka acak

lihat: http://Ruby-doc.org/stdlib-1.9.2/libdoc/securerandom/rdoc/SecureRandom.html

754

Saya menggunakan ini untuk menghasilkan string ramah URL acak dengan panjang maksimum yang dijamin:

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

Ini menghasilkan string acak huruf kecil a-z dan 0-9. Ini tidak sangat dapat dikustomisasi tetapi pendek dan bersih.

236

Solusi ini menghasilkan serangkaian karakter yang mudah dibaca untuk kode aktivasi; Saya tidak ingin orang membingungkan 8 dengan B, 1 dengan I, 0 dengan O, L dengan 1, dll.

# 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

Yang lain menyebutkan sesuatu yang serupa, tetapi ini menggunakan fungsi 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=="

Hasilnya mungkin mengandung A-Z, a-z, 0-9, “-” dan “_”. “=” Juga digunakan jika bantalan benar.

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

Menghasilkan string 8 huruf acak (mis. NVAYXHGR)

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

Menghasilkan string 8 karakter acak (mis. 3PH4SWF2), tidak termasuk 0/1/I/O. Ruby 1.9

45
Shai Coleman

Karena Ruby 2.5 sangat mudah dengan SecureRandom.alphanumeric:

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

Menghasilkan string acak yang mengandung A-Z, a-z dan 0-9 dan karenanya harus berlaku dalam kebanyakan kasus penggunaan. Dan mereka dihasilkan secara acak aman, yang mungkin bermanfaat juga.


Sunting: Sebuah tolok ukur untuk membandingkannya dengan solusi yang memiliki jumlah suara terbanyak:

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)

Jadi solusi Rand hanya membutuhkan sekitar 3/4 dari waktu SecureRandom. Mungkin masalah jika Anda benar-benar menghasilkan banyak string, tetapi jika Anda hanya membuat beberapa string acak dari waktu ke waktu, saya akan selalu menggunakan implementasi yang lebih aman (karena juga lebih mudah dipanggil dan lebih eksplisit).

34
Markus

Saya tidak ingat di mana saya menemukan ini, tetapi sepertinya proses yang terbaik dan paling tidak intensif bagi saya:

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

Jika Anda ingin string dengan panjang tertentu, gunakan:

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

Ini akan menghasilkan string acak dengan panjang 2n berisi 0-9 dan a-f

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

Berikut ini adalah satu baris kode sederhana untuk string acak dengan panjang 8

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

Anda juga dapat menggunakannya untuk kata sandi acak yang panjangnya 8

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

saya harap ini akan membantu dan luar biasa.

10
Awais

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

Waspada: Rand dapat diprediksi untuk penyerang dan karena itu mungkin tidak aman. Anda harus menggunakan SecureRandom jika ini untuk menghasilkan kata sandi. Saya menggunakan sesuatu seperti ini:

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
SecureRandom.base64(15).tr('+/=lIO0', 'pqrsxyz')

Sesuatu dari Rancangan

6
Thorpe Obazee

Cukup tambahkan sen saya di sini ...

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

anda dapat menggunakan String#random dari Facet of Ruby Gem facets:

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

pada dasarnya melakukan ini:

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

Metode lain yang saya suka gunakan

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

Tambahkan ljust jika Anda benar-benar paranoid tentang panjang string yang benar:

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

Saya pikir ini keseimbangan keseimbangan, kejelasan, dan kemudahan modifikasi. 

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

Mudah dimodifikasi

Misalnya, termasuk digit:

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

Heksadesimal huruf besar:

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

Untuk serangkaian karakter yang benar-benar mengesankan:

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

Favorit saya adalah (:A..:Z).to_a.shuffle[0,8].join. Perhatikan bahwa shuffle memerlukan Ruby> 1.9.

4
Josh

Solusi ini membutuhkan ketergantungan eksternal, tetapi tampaknya lebih cantik daripada yang lain.

  1. Pasang permata faker
  2. Faker::Lorem.characters(10) # => "ang9cbhoa8"
4
asiniy

Diberikan:

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

Ekspresi tunggal, dapat disampaikan sebagai argumen, memungkinkan karakter duplikat:

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

2 sen saya:

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

Saya hanya menulis permata kecil random_token untuk menghasilkan token acak untuk kebanyakan kasus penggunaan, selamat menikmati ~

https://github.com/sibevin/random_token

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

Saya melakukan sesuatu seperti ini baru-baru ini untuk menghasilkan string acak 8 byte dari 62 karakter. Karakternya 0-9, a-z, A-Z. Saya memiliki array dari mereka seperti yang berulang 8 kali dan memilih nilai acak dari array. Ini ada di dalam aplikasi Rails.

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

Yang aneh adalah saya mendapat duplikat dalam jumlah yang banyak. Sekarang secara acak ini seharusnya tidak pernah terjadi. 62 ^ 8 sangat besar, tetapi dari 1.200 kode di db saya memiliki banyak duplikat. Saya perhatikan mereka terjadi pada batas jam satu sama lain. Dengan kata lain saya mungkin melihat duple di 12:12:23 dan 2:12:22 atau sesuatu seperti itu ... tidak yakin apakah waktu adalah masalah atau tidak.

Kode ini ada di sebelum membuat objek activerecord. Sebelum catatan dibuat, kode ini akan menjalankan dan menghasilkan kode 'unik'. Entri dalam db selalu diproduksi dengan andal, tetapi kode (str pada baris di atas) terlalu sering diduplikasi.

Saya membuat skrip untuk menjalankan melalui 100000 iterasi dari baris di atas dengan penundaan kecil sehingga butuh 3-4 jam berharap untuk melihat semacam pola pengulangan setiap jam, tetapi tidak melihat apa pun. Saya tidak tahu mengapa ini terjadi di aplikasi Rails saya.

3
erik

Jika Anda menggunakan UNIX dan Anda masih harus menggunakan Ruby 1.8 (tanpa SecureRandom) tanpa Rails, Anda juga dapat menggunakan ini:

random_string = `openssl Rand -base64 24`

Catatan ini memunculkan Shell baru, ini sangat lambat dan hanya dapat direkomendasikan untuk skrip.

2
lzap

Trik lain yang bekerja dengan Ruby 1.8+ dan cepat adalah:

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

Itu membuat Anda string hex acak. Cara serupa Anda harus dapat menghasilkan string base64 ('M *').

2
lzap

Saya suka jawaban Radar, sejauh ini, saya pikir. Saya akan Tweak sedikit seperti ini:

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

Bidikan terbaik saya, 2 solusi untuk string acak yang terdiri dari 3 rentang

(('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

coba ini

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

Saya suka jawaban utasnya, memang sangat membantu !, tetapi jika saya dapat mengatakan, tidak ada satu pun yang memuaskan saya, mungkin metode Rand (). sepertinya tidak tepat bagi saya, karena kita punya metode # pilihan Array dalam hal ini.

2

Inilah metode lain:

  • Ini menggunakan generator nomor acak aman bukan Rand ()
  • Dapat digunakan dalam URL dan nama file
  • Berisi huruf besar, huruf kecil dan angka
  • Memiliki opsi untuk tidak menyertakan karakter ambigu I0l01

Membutuhkan require "securerandom"

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

Ini didasarkan pada beberapa jawaban lain, tetapi menambah sedikit kerumitan:

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

Intinya memastikan kata sandi yang panjangnya 8 - 20 karakter, dan yang mengandung setidaknya satu angka dan satu karakter khusus.

1
Chris Bloom

Untuk merancang secure_validatable Anda dapat menggunakan ini

(0 ... 8) .map {([65, 97]. Sample + Rand (26)). Chr} .Push (Rand (99)) .gabung

1
shiva kumar

Ini adalah peningkatan dari jawaban @Travis R:

 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

Di @Travis R, karakter dan angka menjawab bersamaan, jadi terkadang random_string hanya dapat mengembalikan angka atau hanya karakter. Dengan peningkatan ini setidaknya setengah dari random_string akan berupa karakter dan sisanya adalah angka. Untuk jaga-jaga jika Anda membutuhkan string acak dengan angka dan karakter

0
Lucas Andrade

Untuk menjadikan pertama Anda menjadi satu pernyataan:

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

Cara termudah adalah dengan menggunakan permata string_pattern https://github.com/MarioRuiz/string_pattern

Misalnya untuk menghasilkan 36 huruf acak:

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

Anda juga dapat menggunakan ekspresi reguler

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

Buat string kosong atau pra-perbaikan jika perlu:

myStr = "OID-"

Gunakan kode ini untuk mengisi string dengan angka acak:

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

Catatan:

(Rand * 43) + 47).ceil

Ini akan menghasilkan angka acak dari 48-91 (0,1,2..Y, Z)

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

Ini digunakan untuk melewati karakter khusus (karena saya tidak tertarik untuk memasukkannya)

while(myStr.length < 12)

Ini akan menghasilkan total 12 karakter string panjang termasuk awalan.

Output sampel:

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

atau

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

Kami telah menggunakan ini pada kode kami:

class String

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

end

Panjang maksimum yang didukung adalah 25 (kami hanya menggunakannya dengan default, jadi belum menjadi masalah).

Seseorang menyebutkan bahwa 'a' .. 'z' adalah suboptimal jika Anda ingin sepenuhnya menghindari menghasilkan kata-kata ofensif. Salah satu ide yang kami miliki adalah menghapus vokal, tetapi Anda masih berakhir dengan WTFBBQ dll.

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

Inilah solusi yang fleksibel dan memungkinkan dups:

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

Contoh:

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

Anda juga dapat mengizinkan karakter tertentu muncul lebih sering:

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

Penjelasan: Metode di atas mengambil karakter dari string yang diberikan dan menghasilkan array yang cukup besar. Kemudian mengocoknya, mengambil n item pertama, lalu bergabung dengan mereka.

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

Gunakan Permata 'SafeRandom' GithubLink

Ini akan memberikan cara termudah untuk menghasilkan nilai acak untuk Rails2, Rails 3, Rails 4, Rails 5 kompatibel. 

0
Rubyist