Offizielle Ruby FAQ
Wenn Sie Fehler melden oder Verbesserungen für diese FAQ vorschlagen möchten, besuchen Sie bitte unser GitHub-Repository und öffnen Sie ein Issue oder einen Pull Request.
Eingebaute Bibliotheken
Was gibt instance_methods(false) zurück?
Die Methode instance_methods gibt ein Array zurück, das die Namen der Instanzmethoden in der empfangenden Klasse oder dem Modul enthält. Dies schließt die Methoden in Oberklassen und in eingebundenen Modulen ein.
instance_methods(false) oder instance_methods(nil) geben die Namen nur derjenigen Methoden zurück, die im Empfänger definiert sind.
Wie funktionieren Zufallszahlensamen?
Wenn rand ohne vorherigen Aufruf von srand aufgerufen wird, verwendet Rubys Pseudo-Zufallszahlengenerator einen zufälligen (gewissermaßen) Samen, der unter anderem eine vom Betriebssystem bereitgestellte Entropiequelle nutzt, falls verfügbar. Aufeinanderfolgende Ausführungen eines Programms, das srand nicht verwendet, erzeugen unterschiedliche Zufallszahlenfolgen.
Zu Testzwecken können Sie ein vorhersagbares Verhalten mit derselben Zahlenreihe bei jeder Programmausführung erzielen, indem Sie srand mit einem konstanten Samen aufrufen.
Ich habe eine Datei gelesen und geändert, aber die Datei auf der Festplatte hat sich nicht geändert.
File.open("example", "r+").readlines.each_with_index do |line, i|
line[0,0] = "#{i+1}: "
end
Dieses Programm fügt der Datei example *keine* Zeilennummern hinzu. Es liest zwar den Inhalt der Datei, und für jede gelesene Zeile wird die Zeilennummer vorangestellt, aber die Daten werden nie zurückgeschrieben. Der folgende Code aktualisiert die Datei *doch* (wenn auch auf etwas gefährliche Weise, da er vor Beginn der Aktualisierung keine Sicherung erstellt).
File.open("example", "r+") do |f|
lines = f.readlines
lines.each_with_index {|line, i| line[0,0] = "#{i+1}: " }
f.rewind
f.puts lines
end
Wie kann ich eine Datei verarbeiten und ihren Inhalt aktualisieren?
Mit der Kommandozeilenoption -i oder der integrierten Variablen $-i können Sie eine Datei lesen und ersetzen.
Der Code in der vorherigen Frage, der Zeilennummern zu einer Datei hinzufügte, wäre wahrscheinlich am besten mit dieser Technik zu schreiben.
$ ruby -i -ne 'print "#$.: #$_"' example
Wenn Sie die Originaldatei behalten möchten, verwenden Sie -i.bak, um eine Sicherungskopie zu erstellen.
Ich habe eine Datei geschrieben und kopiert, aber das Ende der Kopie scheint verloren zu sein.
Dieser Code funktioniert nicht richtig.
require "fileutils"
File.open("file", "w").puts "This is a file."
FileUtils.cp("file", "newfile")
Da die E/A gepuffert ist, wird file kopiert, bevor dessen Inhalt auf die Festplatte geschrieben wurde. newfile ist wahrscheinlich leer. Wenn das Programm jedoch beendet wird, werden die Puffer geleert, und file hat den erwarteten Inhalt.
Das Problem tritt nicht auf, wenn Sie sicherstellen, dass file vor dem Kopieren geschlossen wird.
require "fileutils"
File.open("file", "w") {|f| f.puts "This is a file." }
FileUtils.cp("file", "newfile")
Wie erhalte ich die Zeilennummer in der aktuellen Eingabedatei?
Beim Lesen einer Datei erhöht Ruby einen Zeilennummern-Zähler in der globalen Variable $.. Dieser ist auch über das Attribut lineno des File-Objekts verfügbar.
Die spezielle Konstante ARGF ist ein dateiähnliches Objekt, das zum Lesen aller auf der Kommandozeile angegebenen Eingabedateien (oder der Standardeingabe, falls keine Dateien vorhanden sind) verwendet werden kann. ARGF wird implizit von Code wie diesem verwendet:
while gets
print $_
end
In diesem Fall ist $. die kumulative Anzahl der gelesenen Zeilen über alle Eingabedateien hinweg. Um die Zeilennummer in der aktuellen Datei zu erhalten, verwenden Sie:
ARGF.file.lineno
Sie können den Namen der aktuellen Datei auch über ARGF.file.path abrufen.
Wie kann ich less verwenden, um die Ausgabe meines Programms anzuzeigen?
Ich habe Folgendes versucht, aber nichts kam heraus:
open("|less", "w").puts "abc"
Das liegt daran, dass das Programm sofort endet und less keine Chance hat, das von Ihnen Geschriebene zu sehen, geschweige denn anzuzeigen. Stellen Sie sicher, dass die E/A ordnungsgemäß geschlossen wird, und es wartet, bis less endet.
open("|less", "w") {|f| f.puts "abc" }
Was passiert mit einem File-Objekt, auf das nicht mehr verwiesen wird?
Ein File-Objekt, auf das nicht mehr verwiesen wird, wird für die Garbage Collection berechtigt. Die Datei wird automatisch geschlossen, wenn das File-Objekt von der Garbage Collection aufgeräumt wird.
Ich fühle mich unwohl, wenn ich eine Datei nicht schließe.
Es gibt mindestens vier gute Möglichkeiten, um sicherzustellen, dass Sie eine Datei schließen:
# (1)
f = File.open("file")
begin
f.each {|line| print line }
ensure
f.close
end
# (2)
File.open("file") do |f|
f.each {|line| print line }
end
# (3)
File.foreach("file") {|line| print line }
# (4)
File.readlines("file").each {|line| print line }
Wie kann ich Dateien nach ihrem Änderungsdatum sortieren?
Dir.glob("*").sort {|a, b| File.mtime(b) <=> File.mtime(a) }
Obwohl dies funktioniert (und eine Liste in umgekehrt chronologischer Reihenfolge zurückgibt), ist es nicht sehr effizient, da es die Änderungszeiten der Dateien bei jedem Vergleich vom Betriebssystem abruft.
Mehr Effizienz kann mit etwas zusätzlicher Komplexität erreicht werden.
Dir.glob("*").map {|f| [File.mtime(f), f] }.
sort {|a, b| b[0] <=> a[0] }.map(&:last)
Wie kann ich die Worthäufigkeit in einer Datei zählen?
freq = Hash.new(0)
File.read("example").scan(/\w+/) {|word| freq[word] += 1 }
freq.keys.sort.each {|word| puts "#{word}: #{freq[word]}" }
Erzeugt
and: 1
is: 3
line: 3
one: 1
this: 3
three: 1
two: 1
Wie sortiere ich Zeichenketten alphabetisch?
Wenn Sie möchten, dass Ihre Zeichenketten "AAA", "BBB", ..., "ZZZ", "aaa", "bbb" sortiert werden, funktioniert der integrierte Vergleich problemlos.
Wenn Sie die Groß-/Kleinschreibung ignorieren möchten, vergleichen Sie die kleingeschriebenen Versionen der Zeichenketten im Sortierblock.
array = %w( z bB Bb bb Aa BB aA AA aa a A )
array.sort {|a, b| a.downcase <=> b.downcase }
# => ["a", "A", "Aa", "aA", "AA", "aa", "bB", "Bb", "bb", "BB", "z"]
Wenn Sie so sortieren möchten, dass "A" und "a" zusammenkommen, "a" aber als größer als "A" betrachtet wird (sodass "Aa" nach "AA" aber vor "AB" kommt), verwenden Sie:
array.sort {|a, b| (a.downcase <=> b.downcase).nonzero? || a <=> b }
# => ["A", "a", "AA", "Aa", "aA", "aa", "BB", "Bb", "bB", "bb", "z"]
Wie kann ich Tabs in Leerzeichen umwandeln?
Wenn a die zu erweiternde Zeichenkette enthält, können Sie eine der folgenden Optionen verwenden:
1 while a.sub!(/(^[^\t]*)\t(\t*)/){$1+" "*(8-$1.size%8+8*$2.size)}
# or
1 while a.sub!(/\t(\t*)/){" "*(8-$~.begin(0)%8+8*$1.size)}
# or
a.gsub!(/([^\t]{8})|([^\t]*)\t/n){[$+].pack("A8")}
Wie kann ich einen Backslash in einem regulären Ausdruck maskieren?
Regexp.quote('\\') maskiert einen Backslash.
Es wird kniffliger, wenn Sie sub und gsub verwenden. Nehmen wir an, Sie schreiben gsub(/\\/, '\\\\') in der Hoffnung, jeden Backslash durch zwei zu ersetzen. Das zweite Argument wird bei der Syntaxanalyse zu '\\' konvertiert. Bei der Ersetzung wandelt die Regex-Engine dies in '\' um, sodass der Nettoeffekt darin besteht, jeden einzelnen Backslash durch einen weiteren einzelnen Backslash zu ersetzen. Sie müssen gsub(/\\/, '\\\\\\') schreiben!
Wenn Sie jedoch die Tatsache nutzen, dass \& den übereinstimmenden String enthält, könnten Sie auch gsub(/\\/, '\&\&') schreiben.
Wenn Sie die Blockform von gsub verwenden, d. h. gsub(/\\/) { '\\\\' }, wird die Zeichenkette für die Ersetzung nur einmal analysiert (während des Syntaxdurchlaufs) und das Ergebnis ist das, was Sie beabsichtigt haben.
Was ist der Unterschied zwischen sub und sub!?
Bei sub wird eine Kopie des Empfängers generiert, ersetzt und zurückgegeben.
Bei sub! wird der Empfänger geändert und zurückgegeben, wenn eine Übereinstimmung gefunden wurde. Andernfalls wird nil zurückgegeben.
Methoden wie sub!, die das Attribut des Empfängers ändern, werden als destruktive Methoden bezeichnet. Normalerweise hat, wenn es zwei ähnliche Methoden gibt und eine davon destruktiv ist, die destruktive Methode das Suffix !.
def foo(str)
str.sub(/foo/, "baz")
end
obj = "foo"
foo(obj) # => "baz"
obj # => "foo"
def foo(str)
str.sub!(/foo/, "baz")
end
foo(obj) # => "baz"
obj # => "baz"
Wo passt \Z?
\Z passt direkt vor dem letzten \n (Zeilenumbruch), wenn die Zeichenkette mit einem \n endet, andernfalls passt es am Ende einer Zeichenkette.
Was ist der Unterschied zwischen thread und fork?
Dieser Abschnitt oder Teile davon könnten veraltet oder nicht bestätigt sein.
Ruby-Threads werden innerhalb des Interpreters implementiert, während fork das Betriebssystem aufruft, um einen separat ausgeführten Unterprozess zu erstellen.
Thread und Fork haben die folgenden Eigenschaften:
forkist langsam,threadist es nicht.forkteilt sich nicht den Speicherbereich.threadverursacht kein Thrashing.threadfunktioniert unter DOS.- Wenn
threadin eine Deadlock-Situation gerät, stoppt der gesamte Prozess. forkkann Pausen nutzen, die auf den Abschluss von E/A warten.threadtut dies nicht (zumindest nicht ohne Hilfe).
Sie sollten fork und thread wahrscheinlich nicht mischen.
Wie kann ich Marshal verwenden?
Marshal wird verwendet, um ein Objekt in einer Datei oder einer Zeichenkette zu speichern und später wiederherzustellen. Objekte können gespeichert werden mit:
Marshal.dump( obj [, io ] [, lev] )
io ist ein beschreibbares IO-Objekt, lev bezeichnet die Ebene, auf die Objekte verzweigt und gespeichert werden. Wenn lev Ebenen des Verzweigens durchgeführt werden und Objektverweise noch vorhanden sind, speichert dump nur den Verweis, nicht das referenzierte Objekt. Das ist nicht gut, da diese referenzierten Objekte später nicht wiederhergestellt werden können.
Wenn io weggelassen wird, werden die gemarschelten Objekte in einer Zeichenkette zurückgegeben.
Sie können Objekte mit folgender Methode wieder laden:
obj = Marshal.load(io)
# or
obj = Marshal.load(str)
wobei io ein lesbares IO-Objekt ist und str die gedumpte Zeichenkette ist.
Wie kann ich trap verwenden?
trap ordnet Codeblöcke externen Ereignissen (Signalen) zu.
trap("PIPE") { raise "SIGPIPE" }