当前位置:  开发笔记 > 后端 > 正文

如何在Ruby中生成随机字符串

如何解决《如何在Ruby中生成随机字符串》经验,为你挑选了21个好方法。

我正在为"A"生成一个8个字符的伪随机大写字符串."Z":

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

但它看起来并不干净,并且它不能作为参数传递,因为它不是单个语句.要获得一个混合大小写的字符串"a".."z"加上"A".."Z",我将其更改为:

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

但它看起来像垃圾.

有没有人有更好的方法?



1> Kent Fredric..:
(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


34个字符和超快速:`('a'..'z').to_a.shuffle [0,8] .join`.注意你需要Ruby> = 1.9到`shuffle`.
`[*('a'..'z'),*('0'..'9')].shuffle [0,8] .join`生成一个包含字母和数字的随机字符串.
`rand`具有确定性和可预测性.不要用它来生成密码!使用其中一个`SecureRandom`解决方案.
@faraz你的方法在功能上是不一样的,它不随机替换.
除非您有自己的驱动程序,否则最好利用现有的库.在其他答案中,请参阅`SecureRandom`作为一个示例.
使用`shuffle`的解决方案不会那么棒,因为它们会产生一次出现字符的字符串(所以字符串如"gbalgqut"将是不可能的 - 双"g")
始终使用SecureRandom等现有解决方案,转而采用自行开发的"随机"解决方案.说真的,他们是有原因的.
最后一个例子应该是`(0 ... 50).map {[('a'..'z'),('A'..'Z')].flat_map(&:to_a).sample}.加入`你肯定*没有*花费很多时间打高尔夫xD
我刚刚创建了一个模块“ RandomString”,总结了所有答案中提到的三种主要技术:https://gist.github.com/jopotts/8706578
@TanelSuurhans作为这个答案的OP,我同意所有关于"使用经过验证的测试工具"的观点.就在这个答案的时候,这些工具还不是核心,作者似乎把打高尔夫作为一个目标.了解您的语言如何工作与使用该语言编写的工具一样重要.

2> 小智..:

为什么不使用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


顺便说一句,它是1.9和最近的1.8版本中的stdlib的一部分,所以可以只需要'secure'ndom'`来获得这个整洁的`SecureRandom`帮助器:)
BTW SecureRandom已从3.2版的ActiveSupport中删除.来自更改日志:"从标准库中删除了ActiveSupport :: SecureRandom以支持SecureRandom".
`SecureRandom.random_number(36**12).to_s(36).rjust(12,"0")`将生成一个0-9a-z(36个字符)的字符串,总长度为12个字符.将12更改为您想要的任何长度.不幸的是,没有办法只使用`Integer#to_s`获得AZ.
base64会,但不是像他的例子中的十六进制

3> 小智..:

我使用它来生成具有保证最大长度的随机URL友好字符串:

rand(36**length).to_s(36)

它生成小写az和0-9的随机字符串.它不是很可定制,但它简洁干净.


这是一个很好的解决方案(并且速度很快),但它偶尔会产生一个低于*`length`长度的字符串*,大约一次在~40
这里的版本总是产生所需长度的标记:`(36**(长度-1)+兰特(36**长度 - 36**(长度-1))).to_s(36)`
@Brian E这将保证你想要的数字:`(36**(长度-1)+兰特(36**长度)).to_s(36)`.36**(长度-1)转换为基数36是10**(长度-1),这是具有您想要的数字长度的最小值.
最短版本的+1(不调用外部二进制文件^^).如果随机字符串不是公开的,我有时甚至只使用`rand.to_s`; 丑陋,但有效.
这在Rails 4和Ruby 2.1.1中为我吐出错误:`NameError:undefined局部变量或main:Object的方法`length'

4> 小智..:

该解决方案为激活码生成一串易于阅读的字符; 我不希望人们混淆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


@gtd - 是的.U和V是ambigvov.
为了安全起见,您还需要使用`SecureRandom.random_number(charset.size)`而不是`rand(charset.size)`
'U'是暧昧还是错字?

5> Travis Reede..:

其他人提到类似的东西,但这使用了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," - "和"_".如果填充为真,则也使用"=".



6> Markus..:

由于ruby 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)

所以rand解决方案只需要大约3/4的时间SecureRandom.如果你生成了很多字符串可能很重要,但如果你不时创建一些随机字符串,我总是会使用更安全的实现(因为它也更容易调用和更明确).



7> Shai Coleman..:
[*('A'..'Z')].sample(8).join

生成一个随机的8个字母的字符串(例如NVAYXHGR)

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

生成随机8字符串(例如3PH4SWF2),不包括0/1/I/O. Ruby 1.9


唯一的问题是结果中的每个字符都是唯一的.限制可能的值.

8> Travis Reede..:

我不记得我发现了什么,但对我来说似乎是最好的,也是最不重要的过程:

def random_string(length=10)
  chars = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ0123456789'
  password = ''
  length.times { password << chars[rand(chars.size)] }
  password
end


也许你在这里找到了它?http://travisonrails.com/2007/06/07/generate-random-text-with-ruby
故意丢失了"0"和"1"以及"O"和"我",因为这些字符含糊不清.如果使用此类代码生成用户需要复制的一组字符,则最好排除可能难以区分的字符.

9> 小智..:
require 'securerandom'
SecureRandom.urlsafe_base64(9)


顺便说一句,urlsafe_base64返回一个字符串,大约是指示长度的4/3.要获得一个字符串n chars long,请尝试`n = 9; SecureRandom.urlsafe_base64(N)[0..N-1]`

10> 小智..:

如果需要指定长度的字符串,请使用:

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

它将生成一个2n包含0-9和的随机字符串长度a-f



11> gr8scott06..:

Array.new(n){[*"0".."9"].sample}.join,在你的情况下n = 8.

广义:n=8等等 - 从这个答案



12> 小智..:
require 'sha1'
srand
seed = "--#{rand(10000)}--#{Time.now}--"
Digest::SHA1.hexdigest(seed)[0,8]


请记住,十六进制摘要仅返回0-9和af字符.

13> Ragmaanir..:

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"



14> Awais..:

这是一行长度为8的随机字符串简单代码

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

您也可以将它用于长度为8的随机密码

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

我希望它会有所帮助和惊人.


您不应该使用它来生成自己的密码,因为此方法永远不会重复一个字符.因此,你只使用8个字符的可能字符空间的'P(36,8)/ 36 ^ 8 = 0.4`(~2x更容易暴力)或'P(36,25)/ 36 ^ 25 = 0.00001 `25个字符的可能字符空间(~100,000x更容易暴力).

15> Thaha kp..:

这是一个简单的随机密码代码,带有lenth 8

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

希望它会有所帮助.



16> pencil..:

请注意:rand攻击者可以预测,因此可能不安全.如果这是用于生成密码,您肯定应该使用SecureRandom.我使用这样的东西:

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



17> user163365..:

我喜欢使用的另一种方法

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

如果您对正确的字符串长度非常偏执,请添加:

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



18> Teej..:
SecureRandom.base64(15).tr('+/=lIO0', 'pqrsxyz')

来自Devise的东西



19> Nathan Long..:

我认为这是简洁,清晰和易于修改的良好平衡.

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

轻松修改

例如,包括数字:

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

大写十六进制:

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

对于真正令人印象深刻的人物阵列:

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



20> pduersteler..:

在这里加我的分钱......

def random_string(length = 8)
  rand(32**length).to_s(32)
end


注意:这并不总是正确地返回一个字符串+长度+长 - 它可能更短.这取决于`rand`返回的数字

21> Tilo..:

你可以使用String#randomRuby Gem的Facets facets:

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

它基本上是这样的:

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

推荐阅读
雯颜哥_135
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有