it-swarm-eu.dev

So generieren Sie eine zufällige Zeichenfolge in Ruby

Ich generiere gerade eine 8-stellige pseudozufällige Großbuchstabenfolge für "A" .. "Z":

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

es sieht jedoch nicht sauber aus und kann nicht als Argument übergeben werden, da es keine einzige Anweisung ist. Um eine Zeichenfolge "a" .. "z" plus "A" .. "Z" zu erhalten, habe ich sie geändert:

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

aber es sieht aus wie Müll.

Hat jemand eine bessere Methode?

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

Ich verbringe zu viel Zeit mit Golf.

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

Und eine letzte, die noch verwirrender ist, aber flexibler ist und weniger Zyklen verbraucht:

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

Warum nicht SecureRandom verwenden?

require 'securerandom'
random_string = SecureRandom.hex

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

SecureRandom bietet auch Methoden für:

  • base64
  • random_bytes
  • zufallszahl

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

754

Ich verwende dies zum Generieren von URL-freundlichen Zeichenfolgen mit einer garantierten maximalen Länge:

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

Es erzeugt zufällige Zeichenfolgen aus Kleinbuchstaben von a-z und 0-9. Es ist nicht sehr anpassbar, aber kurz und sauber.

236

Diese Lösung generiert eine Folge leicht lesbarer Zeichen für Aktivierungscodes. Ich wollte nicht, dass die Leute 8 mit B verwechseln, 1 mit I, 0 mit O, L mit 1 usw.

# 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

Andere haben etwas ähnliches erwähnt, aber dies verwendet die URL-sichere Funktion.

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

Das Ergebnis kann A-Z, a-z, 0-9, "-" und "_" enthalten. “=” Wird auch verwendet, wenn das Auffüllen wahr ist.

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

Eine zufällige Zeichenfolge mit 8 Buchstaben erstellen (z. B. NVAYXHGR)

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

Generieren Sie eine zufällige 8-stellige Zeichenfolge (z. B. 3PH4SWF2), ausgenommen 0/1/I/O. Ruby 1,9

45
Shai Coleman

Seit Ruby 2.5 wirklich einfach mit SecureRandom.alphanumeric:

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

Erzeugt zufällige Zeichenfolgen mit A-Z, a-z und 0-9 und sollte daher in den meisten Anwendungsfällen anwendbar sein. Und sie werden zufällig sicher generiert, was ebenfalls von Vorteil sein kann.


Edit: Ein Benchmark zum Vergleich mit der Lösung mit den meisten Upvotes:

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)

Die Rand-Lösung benötigt also nur etwa 3/4 der Zeit von SecureRandom. Vielleicht ist es wichtig, wenn Sie wirklich sehr viele Zeichenfolgen generieren, aber wenn Sie nur gelegentlich zufällige Zeichenfolgen erstellen, gehe ich immer mit der sichereren Implementierung (da sie auch einfacher aufzurufen und expliziter ist).

34
Markus

Ich kann mich nicht erinnern, wo ich das gefunden habe, aber es scheint mir das beste und das am wenigsten intensive Verfahren zu sein:

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

Wenn Sie eine Zeichenfolge mit der angegebenen Länge wünschen, verwenden Sie:

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

Es wird eine zufällige Zeichenfolge der Länge 2n generiert, die 0-9 und a-f enthält.

24

Array.new(n){[*"0".."9"].sample}.join, Dabei ist n = 8 in Ihrem Fall.

Generalized: Array.new(n){[*"A".."Z", *"0".."9"].sample}.join usw. - von hier antworten

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

Hier ist ein einfacher Code für eine zufällige Zeichenfolge mit der Länge 8

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

Sie können es auch für ein beliebiges Passwort mit der Länge 8 verwenden

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

ich hoffe es wird helfen und erstaunlich.

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

Beachten Sie: Rand ist für einen Angreifer vorhersehbar und daher wahrscheinlich unsicher. Sie sollten SecureRandom auf jeden Fall verwenden, wenn dies zur Generierung von Passwörtern dient. Ich benutze so etwas:

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

Hier ist ein einfacher Code für ein beliebiges Passwort mit der Länge 8

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

Ich hoffe es wird helfen.

8
Thaha kp
SecureRandom.base64(15).tr('+/=lIO0', 'pqrsxyz')

Etwas von Devise

6
Thorpe Obazee

Einfach meine Cents hier hinzufügen ...

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

sie können String#random aus den Facetten von Ruby Gem facets verwenden:

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

es tut im Grunde Folgendes:

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

Eine andere Methode, die ich gerne benutze

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

Fügen Sie ljust hinzu, wenn Sie wirklich paranoid bezüglich der korrekten Saitenlänge sind:

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

Ich denke, dass dies eine schöne Balance zwischen Prägnanz, Klarheit und einfacher Modifikation ist. 

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

Leicht modifiziert

Zum Beispiel, einschließlich Ziffern:

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

Hexadezimal in Großbuchstaben:

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

Für eine wirklich beeindruckende Reihe von Charakteren:

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

Mein Favorit ist (:A..:Z).to_a.shuffle[0,8].join. Beachten Sie, dass Shuffle Ruby> 1.9 erfordert.

4
Josh

Diese Lösung benötigt externe Abhängigkeit, scheint aber hübscher als eine andere.

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

Gegeben:

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

Einzelner Ausdruck, kann als Argument übergeben werden, ermöglicht doppelte Zeichen:

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

Meine 2 Cent:

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

Ich schreibe einfach einen kleinen Edelstein random_token, um zufällige Token für die meisten Anwendungsfälle zu generieren, ~

https://github.com/sibevin/random_token

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

Ich habe in letzter Zeit so etwas getan, um eine zufällige 8-Byte-Zeichenfolge aus 62 Zeichen zu generieren. Die Zeichen waren 0-9, a-z, A-Z. Ich hatte ein Array von ihnen, als ich 8 Mal in einer Schleife war und einen zufälligen Wert aus dem Array auswählte. Dies war in einer Rails-App.

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

Das Merkwürdige ist, dass ich eine gute Anzahl von Duplikaten bekam. Zufällig sollte das so ziemlich nie passieren. 62 ^ 8 ist riesig, aber von etwa 1200 Codes in der Datenbank hatte ich eine gute Anzahl von Duplikaten. Ich bemerkte, dass sie an stündlichen Grenzen voneinander passierten. Mit anderen Worten, ich könnte ein Duell um 12:12:23 und 2:12:22 oder so ähnlich sehen ... nicht sicher, ob es Zeit ist oder nicht.

Dieser Code befand sich im Vorher-Zustand eines Aktivierungsaufzeichnungsobjekts. Bevor der Datensatz erstellt wurde, würde dieser Code ausgeführt und der "eindeutige" Code generiert. Einträge in der DB wurden immer zuverlässig erzeugt, aber der Code (str in der obigen Zeile) wurde viel zu oft dupliziert.

Ich erstellte ein Skript, um 100000 Iterationen dieser oberen Zeile mit einer kleinen Verzögerung durchzugehen. Es würde 3-4 Stunden dauern, in der Hoffnung, stündlich ein Wiederholungsmuster zu sehen, aber nichts gesehen. Ich habe keine Ahnung, warum dies in meiner Rails-App passiert ist.

3
erik

Wenn Sie sich unter UNIX befinden und Ruby 1.8 (kein SecureRandom) ohne Rails verwenden müssen, können Sie auch Folgendes verwenden:

random_string = `openssl Rand -base64 24`

Beachten Sie, dass dies zu einer neuen Shell führt. Dies ist sehr langsam und kann nur für Skripts empfohlen werden.

2
lzap

Ein weiterer Trick, der mit Ruby 1.8+ funktioniert und schnell geht, ist:

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

Es ist eine zufällige Hex-Zeichenfolge. Auf ähnliche Weise sollten Sie Base64-Zeichenfolge ('M *') generieren können.

2
lzap

Ich mag die Antwort von Radar am besten, denke ich. Ich würde ein bisschen so tweak:

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

Mit dieser Methode können Sie eine beliebige Länge übergeben. Der Standardwert ist 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
2
Ryan Bigg

Mein bester Schuss, 2 Lösungen für eine zufällige Saite bestehend aus 3 Bereichen

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

probiere das aus

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

Ich liebe die Antworten des Threads, war wirklich sehr hilfreich!, Aber wenn ich sagen darf, befriedigt keiner von ihnen meine ayes, vielleicht ist die Rand () - Methode. Es scheint mir einfach nicht richtig zu sein, da wir die Array # Wahlmethode haben.

2

Hier ist eine andere Methode:

  • Es verwendet den sicheren Zufallszahlengenerator anstelle von Rand ().
  • Kann in URLs und Dateinamen verwendet werden
  • Enthält Großbuchstaben, Kleinbuchstaben und Zahlen
  • Hat die Option, keine mehrdeutigen Zeichen I0l01 einzuschließen

Benötigt 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

Dies basiert auf ein paar anderen Antworten, erhöht jedoch die Komplexität:

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

Es stellt im Wesentlichen sicher, dass ein Kennwort zwischen 8 und 20 Zeichen lang ist und mindestens eine Zahl und ein Sonderzeichen enthält.

1
Chris Bloom

Für devise secure_validatable können Sie dies verwenden

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

1
shiva kumar

Hier ist eine Verbesserung der Antwort von @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

Bei @Travis R waren die Antwortzeichen und Zahlen zusammen, sodass random_string manchmal nur Zahlen oder nur Zeichen zurückgeben konnte. Bei dieser Verbesserung besteht mindestens die Hälfte von random_string aus Zeichen und der Rest sind Zahlen. Nur für den Fall, dass Sie eine zufällige Zeichenfolge mit Zahlen und Zeichen benötigen

0
Lucas Andrade

Um Ihre erste Aussage zu machen:

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

Der einfachste Weg ist die Verwendung des Gems string_pattern https://github.com/MarioRuiz/string_pattern

Zum Beispiel um 36 zufällige Buchstaben zu generieren:

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

Sie können auch reguläre Ausdrücke verwenden

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

Erstellen Sie einen leeren String oder einen Pre-Fix, wenn dies erforderlich ist:

myStr = "OID-"

Verwenden Sie diesen Code, um die Zeichenfolge mit Zufallszahlen zu füllen:

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

Anmerkungen:

(Rand * 43) + 47).ceil

Es werden Zufallszahlen von 48-91 (0,1,2..Y, Z) generiert.

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

Es wird verwendet, um Sonderzeichen zu überspringen (da ich nicht daran interessiert bin, sie einzufügen)

while(myStr.length < 12)

Es werden insgesamt 12 Zeichen einschließlich des Präfixes generiert.

Beispielausgabe:

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

oder

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

Wir haben dies in unserem Code verwendet:

class String

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

end

Die maximal unterstützte Länge beträgt 25 (wir verwenden sie nur mit der Standardeinstellung, waren also kein Problem).

Jemand erwähnte, dass 'a' .. 'z' suboptimal ist, wenn Sie völlig vermeiden wollen, beleidigende Wörter zu erzeugen. Eine der Ideen, die wir hatten, bestand darin, Vokale zu entfernen, aber am Ende bleibt WTFBBQ usw.

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

Hier ist eine Lösung, die flexibel ist und Dups ermöglicht:

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

Beispiel:

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

Sie können auch zulassen, dass ein bestimmtes Zeichen häufiger erscheint:

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

Erläuterung: Die obige Methode nimmt die Zeichen einer gegebenen Zeichenfolge und generiert ein ausreichend großes Array. Es mischt es dann, nimmt die ersten n Elemente und fügt sie dann zusammen.

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

Verwenden Sie 'SafeRandom' Gem GithubLink

Es bietet die einfachste Möglichkeit, Zufallswerte für mit Rails2, Rails 3, Rails 4 und Rails 5 kompatible Werte zu generieren. 

0
Rubyist