804

我目前正在为“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}

但它看起来像垃圾。

有没有人有更好的方法?

4

50 回答 50

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

如果要生成一些随机文本,请使用以下命令:

50.times.map { (0...(rand(10))).map { ('a'..'z').to_a[rand(26)] }.join }.join(" ")

此代码生成 50 个单词长度小于 10 个字符的随机单词字符串,然后用空格连接

于 2008-09-17T22:29:05.073 回答
842

为什么不使用 SecureRandom?

require 'securerandom'
random_string = SecureRandom.hex

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

SecureRandom 还具有以下方法:

  • base64
  • 随机字节
  • 随机数

见:http ://ruby-doc.org/stdlib-1.9.2/libdoc/securerandom/rdoc/SecureRandom.html

于 2009-10-25T00:32:57.200 回答
268

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

string_length = 8
rand(36**string_length).to_s(36)

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

于 2010-08-26T07:34:56.553 回答
178

该解决方案为激活码生成一串易于阅读的字符;我不希望人们将 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
于 2009-01-29T20:20:42.053 回答
135

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

于 2011-08-28T18:21:57.950 回答
110

从 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。如果您生成大量字符串,这可能很重要,但如果您只是不时创建一些随机字符串,我总是会选择更安全的实现,因为它也更容易调用和更明确。

于 2018-01-30T12:17:40.417 回答
53
[*('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。红宝石 1.9

于 2012-01-04T16:41:23.317 回答
31

我不记得我在哪里找到的,但对我来说,这似乎是最好的和最少的过程密集型:

def random_string(length=10)
  chars = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ0123456789'
  password = ''
  length.times { password << chars[rand(chars.size)] }
  password
end
于 2009-07-12T21:40:46.857 回答
28
require 'securerandom'
SecureRandom.urlsafe_base64(9)
于 2012-07-13T00:34:57.853 回答
26

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

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

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

于 2013-07-11T14:36:07.180 回答
15

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

广义:Array.new(n){[*"A".."Z", *"0".."9"].sample}.join等。

来自:“生成伪随机字符串AZ,0-9 ”。

于 2014-09-29T19:51:02.673 回答
12

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

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

您还可以将其用于长度为 8 的随机密码:

random_password = ('0'..'z').to_a.shuffle.first(8).join
于 2014-11-19T06:12:15.510 回答
11
require 'sha1'
srand
seed = "--#{rand(10000)}--#{Time.now}--"
Digest::SHA1.hexdigest(seed)[0,8]
于 2008-09-17T22:40:34.640 回答
11

红宝石 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"
于 2010-07-24T21:04:08.310 回答
8

这是长度为 8 的随机密码的一个简单代码:

rand_password=('0'..'z').to_a.shuffle.first(8).join
于 2012-10-15T06:51:24.093 回答
8

请注意: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
于 2013-03-30T14:30:32.087 回答
7

我喜欢使用的另一种方法:

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

ljust如果您对正确的字符串长度真的很偏执,请添加:

 rand(2**256).to_s(36).ljust(8,'a')[0..7]
于 2010-01-08T23:17:16.813 回答
7
SecureRandom.base64(15).tr('+/=lIO0', 'pqrsxyz')

来自设计的东西

于 2012-04-19T00:25:43.200 回答
6

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

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
于 2011-06-20T13:48:42.053 回答
5

只是在这里添加我的美分......

def random_string(length = 8)
  rand(32**length).to_s(32)
end
于 2012-05-27T10:27:32.977 回答
5

您可以String#random从 Ruby Gem 的 Facets 中使用facets

它基本上是这样做的:

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
于 2014-08-22T22:53:52.870 回答
5

此解决方案需要外部依赖,但似乎比其他解决方案更漂亮。

  1. 安装 gem faker
  2. Faker::Lorem.characters(10) # => "ang9cbhoa8"
于 2015-09-18T16:12:49.150 回答
4

我最近正在做这样的事情,从 62 个字符中生成一个 8 字节的随机字符串。字符为 0-9、az、AZ。我有一个数组,就像循环 8 次并从数组中选择一个随机值一样。这是在 Rails 应用程序中。

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

奇怪的是我得到了很多重复。现在随机这几乎不会发生。62^8 是巨大的,但在数据库中的 1200 个左右的代码中,我有很多重复项。我注意到它们发生在彼此的小时边界上。换句话说,我可能会在 12:12:23 和 2:12:22 或类似的时间看到一个重复...不确定时间是否是问题所在。

此代码在 ActiveRecord 对象的创建之前。在创建记录之前,此代码将运行并生成“唯一”代码。数据库中的条目总是可靠地生成,但是代码(str在上面的行中)经常被重复。

我创建了一个脚本来运行上述行的 100000 次迭代,延迟很小,因此希望每小时看到某种重复模式需要 3-4 小时,但什么也没看到。我不知道为什么在我的 Rails 应用程序中会发生这种情况。

于 2010-08-07T20:16:09.540 回答
4

鉴于:

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

单个表达式,可以作为参数传递,允许重复字符:

Array.new(len) { chars.sample }.join
于 2011-04-20T19:58:17.800 回答
4

我最喜欢的是(:A..:Z).to_a.shuffle[0,8].join。请注意,shuffle 需要 Ruby > 1.9。

于 2013-11-28T18:18:17.813 回答
3

我认为到目前为止,我最喜欢雷达的回答。我会像这样调整一下:

CHARS = ('a'..'z').to_a + ('A'..'Z').to_a
def rand_string(length=8)
  s=''
  length.times{ s << CHARS[rand(CHARS.length)] }
  s
end
于 2008-09-18T02:35:00.163 回答
3
''.tap {|v| 4.times { v << ('a'..'z').to_a.sample} }
于 2011-10-04T19:55:02.713 回答
3

由 3 个范围组成的随机字符串的 2 种解决方案:

(('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)*""

每个范围中的一个字符。

如果您需要每个范围内至少一个字符,例如创建一个包含一个大写、一个小写字母和一个数字的随机密码,您可以执行以下操作:

( ('a'..'z').to_a.sample(8) + ('A'..'Z').to_a.sample(8) + (0..9).to_a.sample(8) ).shuffle.join 
#=> "Kc5zOGtM0H796QgPp8u2Sxo1"
于 2012-02-10T20:50:25.963 回答
3

我的 2 美分:

  def token(length=16)
    chars = [*('A'..'Z'), *('a'..'z'), *(0..9)]
    (0..length).map {chars.sample}.join
  end
于 2012-05-03T15:49:14.453 回答
3

我只是写了一个小 gemrandom_token来为大多数用例生成随机令牌,享受吧~

https://github.com/sibevin/random_token

于 2013-12-03T04:01:18.713 回答
2

我们一直在我们的代码中使用它:

class String

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

end

支持的最大长度是 25(无论如何我们只使用默认值,所以没有问题)。

有人提到,如果你想完全避免产生冒犯性的话,'a'..'z' 是次优的。我们的想法之一是删除元音,但你最终还是会得到 WTFBBQ 等。

于 2008-09-17T22:48:38.460 回答
2

使用此方法,您可以传入任意长度。它被设置为默认值 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
于 2008-09-18T00:53:41.403 回答
2

试试这个

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

我喜欢该线程的答案,确实非常有帮助!但如果我可以说,它们都不符合我的要求,也许是 rand() 方法。这对我来说似乎不正确,因为我们已经有了 Array#choice 方法。

于 2011-02-22T04:08:30.597 回答
2

这是另一种方法:

  • 它使用安全随机数生成器而不是 rand()
  • 可用于 URL 和文件名
  • 包含大写、小写字符和数字
  • 可以选择不包含不明确的字符 I0l01

需求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
于 2011-08-24T09:42:14.530 回答
2

如果您在 UNIX 上,并且仍然必须在没有 Rails 的情况下使用 Ruby 1.8(没有 SecureRandom),您也可以使用这个:

random_string = `openssl rand -base64 24`

请注意,这会产生新的 shell,这非常慢,只能推荐用于脚本。

于 2012-07-03T14:23:56.553 回答
2

另一个适用于 Ruby 1.8+ 并且速度很快的技巧是:

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

它得到你随机的十六进制字符串。类似的方式你应该能够生成base64字符串('M *')。

于 2014-08-18T08:01:42.050 回答
1

这是基于其他一些答案,但它增加了一些复杂性:

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

本质上,它确保密码长度为 8 - 20 个字符,并且至少包含一个数字和一个特殊字符。

于 2012-04-24T05:45:19.717 回答
1
10.times do 
  alphabet = ('a'..'z').to_a
  string += alpha[rand(alpha.length)]
end
于 2016-02-24T11:51:09.550 回答
1

对于设计secure_validatable,您可以使用它

(0...8).map { ([65, 97].sample + rand(26)).chr }.push(rand(99)).join

于 2016-05-19T20:11:32.073 回答
1

这是@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

在@Travis R 回答字符和数字在一起,所以有时random_string可能只返回数字或只返回字符。通过这种改进,至少有一半random_string是字符,其余的是数字。以防万一您需要带有数字和字符的随机字符串

于 2018-08-08T15:26:39.403 回答
0

把你的第一个变成一个陈述:

(0...8).collect { |n| value  << (65 + rand(25)).chr }.join()
于 2008-09-17T22:28:35.700 回答
0
`pwgen 8 1`.chomp
于 2010-05-25T20:01:17.107 回答
0

如果需要,创建一个空字符串或前缀:

myStr = "OID-"

使用此代码用随机数填充字符串:

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

笔记:

(rand * 43) + 47).ceil

它将生成 48-91 (0,1,2..Y,Z) 的随机数

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

它用于跳过特殊字符(因为我不想包含它们)

while(myStr.length < 12)

它将生成总共 12 个字符的长字符串,包括前缀。

样本输出:

"OID-XZ2J32XM"
于 2013-04-03T14:18:55.440 回答
0

这是一个灵活且允许重复的解决方案:

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

例子:

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

您还可以允许某个字符更频繁地出现:

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

说明:上述方法采用给定字符串的字符并生成足够大的数组。然后它对其进行洗牌,获取前 n 个项目,然后加入它们。

于 2013-07-30T14:30:21.643 回答
0
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
于 2014-04-26T12:22:23.387 回答
0
a='';8.times{a<<[*'a'..'z'].sample};p a

或者

8.times.collect{[*'a'..'z'].sample}.join
于 2016-08-31T09:58:52.833 回答
0

使用 'SafeRandom' Gem GithubLink

它将提供为 Rails2、Rails 3、Rails 4、Rails 5 兼容生成随机值的最简单方法。

于 2018-11-06T12:14:35.390 回答
-1

这几乎是丑陋的,但也许是朝着正确方向迈出的一步?

 (1..8).map{|i| ('a'..'z').to_a[rand(26)]}.join
于 2008-09-17T22:32:34.643 回答
-1

在 ruby​​ 1.9 中,可以使用 Array 的选择方法,该方法从数组中返回随机元素

于 2009-07-21T04:20:31.033 回答
-11

我不知道 ruby​​,所以我不能给你确切的语法,但我会用可接受的字符列表设置一个常量字符串,然后使用子字符串运算符从中挑选一个随机字符。

这里的好处是,如果字符串应该是用户可输入的,那么您可以排除容易混淆的字符,如 l 和 1 和 i、0 和 O、5 和 S 等。

于 2008-09-17T22:29:33.467 回答