首页 文章

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

提问于
浏览
695

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

但它看起来像垃圾 .

有没有人有更好的方法?

30 回答

  • 6

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

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

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

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

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

  • 165

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

    使用此方法,您可以传入一个abitrary长度 . 默认设置为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
    
  • 3

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

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

    鉴于:

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

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

    Array.new(len) { chars.sample }.join
    
  • 30

    因为ruby 2.5真的很容易 SecureRandom.alphanumeric

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

    生成包含A-Z,a-z和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 解决方案只占 SecureRandom 的3/4左右 . 如果你生成了很多字符串可能很重要,但是如果你不时地创建一些随机字符串,我总会选择更安全的实现(因为它也更容易调用和更明确) .

  • 27

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

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

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

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

    其他人提到类似的东西,但这使用URL安全功能 .

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

    结果可能包含A-Z,a-z,0-9,“ - ”和“_” . 如果填充为真,则也使用“=” .

  • 748

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

    广义: Array.new(n){[*"A".."Z", *"0".."9"].sample}.join 等 - 来自this回答

  • 24

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

  • 4
    (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
    
  • 5

    我的2美分:

    def token(length=16)
        chars = [*('A'..'Z'), *('a'..'z'), *(0..9)]
        (0..length).map {chars.sample}.join
      end
    
  • 3
    [*('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

  • 5

    我喜欢使用的另一种方法

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

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

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

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

    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
    
  • 10

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

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

    我认为,到目前为止,我最喜欢Radar的答案 . 我有点像这样调整:

    CHARS = ('a'..'z').to_a + ('A'..'Z').to_a
    def rand_string(length=8)
      s=''
      length.times{ s << CHARS[rand(CHARS.length)] }
      s
    end
    
  • 10

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

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

    希望它会有所帮助 .

  • 3
    require 'securerandom'
    SecureRandom.urlsafe_base64(9)
    
  • 233

    这个解决方案需要外部依赖,但看起来比另一个更漂亮 .

    • 安装宝石faker

    • Faker::Lorem.characters(10) # => "ang9cbhoa8"

  • 27

    我只是写一个小宝石 random_token 为大多数用例生成随机令牌,享受〜

    https://github.com/sibevin/random_token

  • 5

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

  • 122
    SecureRandom.base64(15).tr('+/=lIO0', 'pqrsxyz')
    

    来自Devise的东西

  • 3

    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"
    
  • 45
    ''.tap {|v| 4.times { v << ('a'..'z').to_a.sample} }
    
  • 893

    我最近正在做这样的事情来生成一个由62个字符组成的8字节随机字符串 . 字符为0-9,a-z,A-Z . 我有一个数组,循环8次,并从数组中选择一个随机值 . 这是一个rails应用程序 .

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

    奇怪的是我得到了很多重复的东西 . 现在随机这应该永远不会发生 . 62 ^ 8是巨大的,但在db中1200个左右的代码中有大量重复 . 我注意到它们发生在彼此的小时界限上 . 换句话说,我可能会在12:12:23和2:12:22看到一个重复的东西......或者类似的东西...不确定时间是否是问题 .

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

    我 Build 一个脚本运行上面这行的100000次迭代,延迟很小,所以需要3-4个小时希望每小时看到一些重复模式,但什么都看不见 . 我不知道为什么这会发生在我的rails应用程序中 .

  • 11

    我不记得我在哪里发现了这个,但对我来说这似乎是最好和最少的过程:

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

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

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

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

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

相关问题