Ruby에서 임의의 문자열을 생성하는 방법
현재 "A".. "Z"에 대해 8 자의 의사 임의 대문자 문자열을 생성하고 있습니다.
value = ""; 8.times{value << (65 + rand(25)).chr}
그러나 그것은 깨끗해 보이지 않으며 단일 문이 아니기 때문에 인수로 전달할 수 없습니다. 대소 문자 혼합 문자열 "a".. "z"+ "A".. "Z"를 얻기 위해 다음과 같이 변경했습니다.
value = ""; 8.times{value << ((rand(2)==1?65:97) + rand(25)).chr}
하지만 쓰레기처럼 보입니다.
누구에게 더 나은 방법이 있습니까?
(0...8).map { (65 + rand(26)).chr }.join
나는 골프에 너무 많은 시간을 보낸다.
(0...50).map { ('a'..'z').to_a[rand(26)] }.join
그리고 훨씬 더 혼란 스럽지만 더 유연하고 더 적은 사이클을 낭비하는 마지막 하나 :
o = [('a'..'z'), ('A'..'Z')].map(&:to_a).flatten
string = (0...50).map { o[rand(o.length)] }.join
SecureRandom을 사용하지 않는 이유는 무엇입니까?
require 'securerandom'
random_string = SecureRandom.hex
# outputs: 5b5cd0da3121fc53b4bc84d0c8af2e81 (i.e. 32 chars of 0..9, a..f)
SecureRandom에는 다음과 같은 방법도 있습니다.
- base64
- random_bytes
- random_number
참조 : http://ruby-doc.org/stdlib-1.9.2/libdoc/securerandom/rdoc/SecureRandom.html
최대 길이가 보장 된 임의의 URL 친화적 인 문자열을 생성하는 데 사용합니다.
rand(36**length).to_s(36)
소문자 az 및 0-9의 임의 문자열을 생성합니다. 커스터마이징이 가능하지는 않지만 짧고 깔끔합니다.
이 솔루션은 활성화 코드에 대해 쉽게 읽을 수있는 문자열을 생성합니다. 나는 사람들이 8과 B, 1과 I, 0과 O, L과 1 등을 혼동하는 것을 원하지 않았습니다.
# 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
다른 사람들도 비슷한 것을 언급했지만 이것은 URL 안전 기능을 사용합니다.
require 'securerandom'
p SecureRandom.urlsafe_base64(5) #=> "UtM7aa8"
p SecureRandom.urlsafe_base64 #=> "UZLdOkzop70Ddx-IJR0ABg"
p SecureRandom.urlsafe_base64(nil, true) #=> "i0XQ-7gglIsHGV2_BNPrdQ=="
결과에는 AZ, az, 0-9, "-"및 "_"가 포함될 수 있습니다. 패딩이 참인 경우 "="도 사용됩니다.
루비 2.5는 SecureRandom.alphanumeric
다음 과 같이 정말 쉽습니다 .
len = 8
SecureRandom.alphanumeric(len)
=> "larHSsgL"
AZ, az 및 0-9를 포함하는 임의의 문자열을 생성하므로 대부분의 사용 사례에 적용 할 수 있습니다. 또한 무작위로 안전하게 생성되므로 이점도있을 수 있습니다.
편집 : 가장 많은 찬성 투표를하는 솔루션과 비교하기위한 벤치 마크 :
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)
So the rand
solution only takes about 3/4 of the time of SecureRandom
. Might matter if you generate really a lot of strings, but if you just create some random string from time to time I'd always go with the more secure implementation (since it is also easier to call and more explicit).
[*('A'..'Z')].sample(8).join
Generate a random 8 letter string (e.g. NVAYXHGR)
([*('A'..'Z'),*('0'..'9')]-%w(0 1 I O)).sample(8).join
Generate a random 8 character string (e.g. 3PH4SWF2), excludes 0/1/I/O. Ruby 1.9
I can't remember where I found this, but it seems like the best and the least process intensive to me:
def random_string(length=10)
chars = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ0123456789'
password = ''
length.times { password << chars[rand(chars.size)] }
password
end
require 'securerandom'
SecureRandom.urlsafe_base64(9)
If you want a string of specified length, use:
require 'securerandom'
randomstring = SecureRandom.hex(n)
It will generate a random string of length 2n
containing 0-9
and a-f
Array.new(n){[*"0".."9"].sample}.join
, where n=8 in your case.
Generalized: Array.new(n){[*"A".."Z", *"0".."9"].sample}.join
, etc. - from this answer
require 'sha1'
srand
seed = "--#{rand(10000)}--#{Time.now}--"
Digest::SHA1.hexdigest(seed)[0,8]
Here is one line simple code for random string with length 8
random_string = ('0'..'z').to_a.shuffle.first(8).join
You can also use it for random password having length 8
random_password = ('0'..'z').to_a.shuffle.first(8).join
i hope it will help and amazing.
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"
Here is one simple code for random password with lenth 8
rand_password=('0'..'z').to_a.shuffle.first(8).join
Hope it will help.
Be aware: rand
is predictable for an attacker and therefore probably insecure. You should definitely use SecureRandom if this is for generating passwords. I use something like this:
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
Another method I like to use
rand(2**256).to_s(36)[0..7]
Add ljust if you are really paranoid about the correct string length:
rand(2**256).to_s(36).ljust(8,'a')[0..7]
SecureRandom.base64(15).tr('+/=lIO0', 'pqrsxyz')
Something from Devise
I think this is a nice balance of conciseness, clarity and ease of modification.
characters = ('a'..'z').to_a + ('A'..'Z').to_a
# Prior to 1.9, use .choice, not .sample
(0..8).map{characters.sample}.join
Easily modified
For example, including digits:
characters = ('a'..'z').to_a + ('A'..'Z').to_a + (0..9).to_a
Uppercase hexadecimal:
characters = ('A'..'F').to_a + (0..9).to_a
For a truly impressive array of characters:
characters = (32..126).to_a.pack('U*').chars.to_a
Just adding my cents here...
def random_string(length = 8)
rand(32**length).to_s(32)
end
you can use String#random
from the Facets of Ruby Gem facets
:
it basically does this:
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
My favorite is (:A..:Z).to_a.shuffle[0,8].join
. Note that shuffle requires Ruby > 1.9.
This solution needs external dependency, but seems prettier than another.
- Install gem faker
Faker::Lorem.characters(10) # => "ang9cbhoa8"
Given:
chars = [*('a'..'z'),*('0'..'9')].flatten
Single expression, can be passed as an argument, allows duplicate characters:
Array.new(len) { chars.sample }.join
I was doing something like this recently to generate an 8 byte random string from 62 characters. The characters were 0-9,a-z,A-Z. I had an array of them as was looping 8 times and picking a random value out of the array. This was inside a rails app.
str = '' 8.times {|i| str << ARRAY_OF_POSSIBLE_VALUES[rand(SIZE_OF_ARRAY_OF_POSSIBLE_VALUES)] }
The weird thing is that I got good number of duplicates. Now randomly this should pretty much never happen. 62^8 is huge, but out of 1200 or so codes in the db i had a good number of duplicates. I noticed them happening on hour boundaries of each other. In other words I might see a duple at 12:12:23 and 2:12:22 or something like that...not sure if time is the issue or not.
This code was in the before create of an activerecord object. Before the record was created this code would run and generate the 'unique' code. Entries in the db were always produced reliably, but the code (str in the above line) was being duplicated much too often.
I created a script to run through 100000 iterations of this above line with small delay so it would take 3-4 hours hoping to see some kind of repeat pattern on an hourly basis, but saw nothing. I have no idea why this was happening in my rails app.
''.tap {|v| 4.times { v << ('a'..'z').to_a.sample} }
My 2 cents:
def token(length=16)
chars = [*('A'..'Z'), *('a'..'z'), *(0..9)]
(0..length).map {chars.sample}.join
end
I just write a small gem random_token
to generate random tokens for most use case, enjoy ~
https://github.com/sibevin/random_token
2 solutions for a random string consisting of 3 ranges:
(('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)*""
One Character from each Range.
And if you need at least one character from each range, such as creating a random password that has one uppercase, one lowercase letter and one digit, you can do something like this:
( ('a'..'z').to_a.sample(8) + ('A'..'Z').to_a.sample(8) + (0..9).to_a.sample(8) ).shuffle.join
#=> "Kc5zOGtM0H796QgPp8u2Sxo1"
With this method you can pass in an abitrary length. It's set as a default as 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
참고URL : https://stackoverflow.com/questions/88311/how-to-generate-a-random-string-in-ruby
'Development Tip' 카테고리의 다른 글
충돌이있는 자식 병합을 실행 취소하는 방법 (0) | 2020.09.29 |
---|---|
두 개의 디렉토리 트리가 주어지면 어떤 파일이 다른지 어떻게 알 수 있습니까? (0) | 2020.09.29 |
Java에서 문자열을 어떻게 비교합니까? (0) | 2020.09.29 |
Mercurial과 Git의 차이점은 무엇입니까? (0) | 2020.09.29 |
내 Android 애플리케이션에서 충돌 데이터를 얻으려면 어떻게해야합니까? (0) | 2020.09.29 |