Was ist Ruby?

Werbung
Ruby – Einführung
Gesammeltes für das gemeinsame Studium
Seite 1
Inhaltsverzeichnis
Was ist Ruby? ............................................................................................................................................... 2
Implementierungen .................................................................................................................................. 2
Einsatzbereiche ........................................................................................................................................ 2
Quellen ......................................................................................................................................................... 3
Einige Speziellere Themen.................................................................................................................... 4
Erste Schritte ................................................................................................................................................ 5
Ruby Installation ....................................................................................................................................... 5
Ruby Objekttypen ..................................................................................................................................... 5
Variablen .............................................................................................................................................. 5
Ganzahlwerte (Integers) ....................................................................................................................... 5
Fließkommawerte (Float) ..................................................................................................................... 6
Zeichenketten (Strings) ........................................................................................................................ 6
Arrays.................................................................................................................................................... 7
Hashes (Dictionaries) ............................................................................................................................ 8
Symbole ................................................................................................................................................ 8
Wahrheitswerte (Booleans) ................................................................................................................. 8
Folgen (Ranges) .................................................................................................................................... 8
Konstanten ........................................................................................................................................... 9
Kontrollstrukturen .................................................................................................................................... 9
Verzweigungen (If, else elsif)................................................................................................................ 9
Schleifen (loop do, while, until) .......................................................................................................... 10
Iteratoren ........................................................................................................................................... 10
Code-Blocks ............................................................................................................................................ 10
Was sind Code-Blocks? ....................................................................................................................... 10
Suchen mit Hilfe von Code-Blocks ...................................................................................................... 11
Hashes verbinden mit Hilfe von Code-Blocks..................................................................................... 11
Ranges, Arrays und Hashes mit Hilfe von Code-Blocks verarbeiten .................................................. 11
Sortieren mit Hilfe von Code-Blocks................................................................................................... 12
Werte akkumulieren mit Hilfe von Code-Blocks ................................................................................ 12
Methoden ............................................................................................................................................... 12
Definition uns Aufruf von Methoden ................................................................................................. 12
Definition von Argumenten für Methoden ........................................................................................ 12
Codebeispiele ............................................................................................................................................. 21
Primzahlensieb: .................................................................................................................................. 21
Ruby – Einführung
Gesammeltes für das gemeinsame Studium
Seite 2
Was ist Ruby?
Zitat aus „Programmierung in Ruby, Der Leitfaden der Pragmatischen Programmierer“, Dave Thomas:
„Nimm eine richtig objekt-orientierte Sprache, etwa Smalltalk. Schmeiß die ungewöhnliche Syntax raus
und benutze einen etwas konventionelleren, datei-basierten Quell-Code. Nun füge ein gutes Maß an
Flexibilität und Komfort solcher Sprachen wie Python oder Perl hinzu. Das alles zusammen ergibt Ruby.“
Ruby (englisch für Rubin) ist eine höhere Programmiersprache, die Mitte der neunziger Jahre von dem
Japaner Yukihiro Matsumoto entworfen wurde.
Ruby ist interpretiert und objektorientiert, unterstützt aber mehrere weitere Programmierparadigmen
(unter anderem prozedurale und funktionale Programmierung sowie Nebenläufigkeit), bietet
dynamische Typisierung, Reflexion und automatische Speicherbereinigung (Garbage Collection –
allerdings laut Berichten eher ineffizient). Ruby ist wie Smalltalk vollständig objektorientiert: Alle
Datentypen sind in Ruby Objekte, auch solche, die in vielen anderen Sprachen als primitive Datentypen
gelten, wie etwa Zahlen oder Zeichen. Ruby unterstützt mehrere Ansätze der Vererbung (allerdings nicht
Mehrfachvererbung).
Implementierungen
Die Referenzimplementierung von Ruby (aktuelle Version: 1.9.3) wurde von Yukihiro „Matz“ Matsumoto
als Interpreter in C entworfen und wird meist als MRI (Matz's Ruby Interpreter) oder auch als CRuby
oder MatzRuby bezeichnet und ist derzeit am weitesten verbreitet. Den Kern bildet YARV (Yet Another
Ruby VM), eine virtuelle Maschine. Statt ein Rubyprogramm direkt auszuführen, wird es zunächst in
Bytecode übersetzt und dann von YARV interpretiert, wodurch sich ein Geschwindigkeitsvorteil ergibt.
Der offizielle Interpreter ist als offener Quellcode (C) verfügbar und daher auf jedem System
kompilierbar. Installer (die das Leben deutlich leichter machen) gibt es für Linux, Windows und OS X
sowie einige exotischere Systeme. Es gibt aber z.B. auch Implementierungen von Ruby in Java (JRuby eine Neuimplementierung des Ruby-Interpreters in Java mit dem Ziel, Ruby nahtlos in die Java-Plattform
zu integrieren.) speziell angepasst an bestimmte Systeme/Libraries (z.B. IronRuby - eine
Implementierung, die Ruby ins .NET-Framework integriert und in C# implementiert ist. MacRuby - eine
Implementierung in Objective-C von Apple) und andere.
Einsatzbereiche
Für folgende Einsatzbereiche ist Ruby (wie auch Perl, Python und PHP) beliebt:
Werkzeuge Systemadministration
webbasierte Anwendungen,
Webentwicklung
Prototypen
Wegwerfskripte
Kommandozeilen-orientiert und GUIorientiert
Netzwerk-Tools
Datenbankunterstützung für alle
gängigen SQL-Datenbanken vorhanden
Ruby – Einführung
Gesammeltes für das gemeinsame Studium
Seite 3
Dafür sorgen unter anderem folgende Features:
Textmanipulation
Administration
regexp, Parser, Lexer, Formatierung,
Konverter
syslog
tar, zlib
Encryption
Multithreading
Server/Daemons
XML
Netzwerk
Mail: smtp, pop3, IMAP,
Mailmanipulation, Mailgenerierung
Internet: http, ftp, ssl, eigenständiger
Webserver (webrick), XML
Shell: telnet, ssh
Webentwicklung: mehrere WebFrameworks (Ruby On Rails, Wee,
Amrita, Nitro), Bildbearbeitung mit
ImageMagick
Client/Server Programming: Distributed
Ruby (dRuby)
Socket-Programmierung: tcpsocket,
udpsocket ...
GUI
Fox GUI
Ruby TK
Windows
Zugriff auf Windows API, DLL-Zugriff,
OLE-Zugriff
Registry-Manipulation
Persistenz/Serialisierungssprachen
Datenbank
Zugriff auf alle gängigen SQLDatenbanken
einheitliches Interface, Kapselung der
darunterliegenden Datenbank
objektorientierte Datenbankadapter
(z.B. Nitro/ Og)
PStore - Objekte auf Festplatte ablegen
YAML - Serialisierungssprache, auch
ideal für Configdateien
Quellen
Die Heimatseite von Ruby
http://www.ruby-lang.org/de/
Hier bekommt man die aktuelle Ruby Version (dzt. 1.9.3)
http://www.ruby-lang.org/de/downloads/
Nettes Online-Tutorial (Installation von Ruby nicht nötig)
http://tryruby.org
Weitere interessante Links mit Tutorials (auch Videos) und Beispielen:
http://www.approximity.com/rubybuch2/
http://www.rubyist.net/~slagell/ruby/misc.html
http://showmedo.com/videotutorials/series?name=fXRfVLC1J
http://www.wikidorf.de/reintechnisch/Inhalt/EinladungInRuby
http://hinterkattentuffel.de/ruby/tutorial.htm
http://www.ruby-doc.org/docs/Einfuhrung_in_Ruby/
http://www.zenspider.com/Languages/Ruby/QuickRef.html
Ruby – Einführung
Gesammeltes für das gemeinsame Studium
Seite 4
Ein gutes Einsteigerbuch auf Deutsch und frei verfügbar „Programmierung in Ruby. Der Leitfaden der
Pragmatischen Programmierer“
http://home.vrweb.de/~juergen.katins/ruby/buch/index.html
Und natürlich die offizielle Ruby Dokumentation
http://www.ruby-doc.org/core-1.9.3/
http://www.ruby-doc.org/stdlib-1.9.3/
Die Ruby Wiki (auf Deutsch)
http://wiki.ruby-portal.de/Hauptseite
Auch SelfRuby darf nicht fehlen (wenn auch bei weitem nicht so ausführlich wie SelfHTML)
http://www.joelh.de/selfruby/index.php
Einige Speziellere Themen
Reguläre Ausdrücke in Ruby (deutsch)
http://www.wikidorf.de/reintechnisch/Inhalt/RubyRegExpTutorial
http://www.wikidorf.de/reintechnisch/Inhalt/RubyRegexp
GUI Toolkits für Ruby, für jene die gern Fensterln
http://home.arcor.de/scite/
Anleitung wie man aus Ruby Programmen ausführbare Windows-Programme generiert
http://ocra.rubyforge.org/
Doku und Links zu wichtigen (und weniger wichtigen) Ruby Libraries (wie z.B. Rails (Web Application
Framework) und Yard (Ruby Dokumentation Framework))
http://www.rubydoc.info/
Und für den Fall dass man in der Linux Shell programmieren will/muss hier eine Kurzübersicht zu BASH
http://www.wikidorf.de/reintechnisch/Inhalt/ShellKurzueberblick
ANMERKUNG: In den eingefügten Codeabschnitten sind die angezeigten Anführungszeichen im Text
immer als identisch zu betrachten auch wenn sie am Ausdruck unterschiedlich aussehen.
Ruby – Einführung
Gesammeltes für das gemeinsame Studium
Seite 5
Erste Schritte
Ruby Installation
Am besten (unter Windows) mit dem Installer unter http://rubyinstaller.org/ -> Download -> Version
auswählen (derzeit ist 1.9.3 die aktuellste). Runterladen, Ausführen, Lizenzbedingungen bestätigen und
dann alle Optionen die man möchte ankreuzen und installieren. Damit ist der Ruby Interpreter, die
Interaktive Ruby Shell (irb) und einige Doku installiert.
Für andere Systeme (Linux, OS X) finden sich unter http://www.ruby-lang.org/de/downloads/
Anleitungen für die Installation.
Als Entwicklungsumgebungen bieten sich Netbeans (nur bis Version 6.9.1 unterstützt), Eclipse (Aptana
Studio 3 installieren für Ruby Support) oder Notepad++ (für die die es etwas weniger voluminös mögen)
an.
Ruby Objekttypen
Variablen
Variablen sind Referenzen auf Objekte und sind entweder undefiniert (nil) oder verhalten sich wie
Objekte.
Variablenzuweisung:
{variablenname} = {Wert} z.B.: x = 1
Variablenkonventionen:
Variablen starten mit einem Kleinbuchstaben und benutzen „_“ als Trennzeichen.
Zusatzangaben bei Variablen (Sichtbarkeit):
Die Sichtbarkeit (Gültigkeit) von Variablen wird in Ruby durch das Voranstellen von „$“ für globale
Variablen und „@“ für Instanz- bzw. „@@“ für Klassenvariablen gekennzeichnet. Alle anderen Variablen
sind Lokale bzw. Blockvariablen.
Ganzahlwerte (Integers)
Bignum und Fixnum
Integerwerte gehören einer von 2 Subklassen der Klasse Integer an. „Fixnum“ und „Bignum“ die sich nur
durch die Art der Speicherung unterscheiden. Dabei kann Bignum wirklich groß werden (probiere 9999
** 9999).
Basisoperationen
+, -, *, /, % (Divisionsrest), ** (Potenz), & (Bitweises Und), | (Bitweises Oder), ^ (Bitweises exclusives
Oder), >> (Bitshift nach rechts), << (Bitshift nach links)
Zuweisungen
Wie in anderen Programmiersprachen auch ist die Zuweisung verkürzbar. Z.B. x = x + 2 kann auf
x +=2 verkürzt werden. Dies funktioniert aber hier mit jedem (!) Operator.
Wichtige Methoden der Integer Klassen
.abs (Absolutwert), .even?, .odd? (Test auf gerade bzw. ungerade), [n] (n-tes Bit der Zahl), .to_f (in Float
umwandel), .to_s (in String umwandeln), .to_s(basis) (in String umwandeln mit angegebene Basis von 2
bis 36), .size (Speichergröße in Byte, für Bignum interessant).
Ruby – Einführung
Gesammeltes für das gemeinsame Studium
Seite 6
Fließkommawerte (Float)
Die Float-Klasse
Float-Werte werden durch den Dezimalpunkt „.“ gekennzeichnet. Sobald bei einer Operation ein FloatWert verwendet wird, wird auch das Ergebnis als Float-Wert berechnet. Allerdings liegt hier eine
gemeine Falle verborgen, da auch das umgekehrte gilt. Wo kein Float-Wert in einer Rechnung
enthalten ist, wird auch kein Float-Wert berechnet. So ergibt z.B. 10 / 3 den Integer-Wert 3. Möchte
man genau rechnen, so muss man entweder 10 / 3.0 oder 10.0 / 3 oder 10.0 / 3.0
angeben. In allen drei Fällen erhält man den erwarteten Wert 3.3333333333333.
Wichtige Methoden der Float-Klasse
.round (für kaufmännische Rundung), .floor (für Abrundung), .ceil (für Aufrundung), .to_i (für
Abschneiden der Nachkommastellen, auch .to_int oder .truncate) -> alle Methoden liefern einen
Integerwert zurück
.round(Stellen) (für Kaufmännische Rundung auf die angegebene Stellenanzahl)
Außerdem sind alle Operationen und Methoden der Integer-Klassen anwendbar bis auf die bitweisen
Operationen (&,|,^,>>,<<, to_s(basis), [n]) sowie even? und odd?.
Zeichenketten (Strings)
Was sind Strings?
Strings sind beliebig lange Zeichenketten in einfachen (‘) oder doppelten (“) Anführungszeichen wobei
in der Doppelanführungszeichen-Version einen Auswertung von sogenannten Escape-Zeichen erfolgt.
Beachte den Unterschied zwischen puts “\ta\tb\nc\nd“ und puts ‘\ta\tb\nc\nd‘ .
In dieser Version ist es auch möglich Variablen auszuwerten die wie folgt gekennzeichnet werden:
#{Variablenname}
also z.B.:
puts “Ihr Name ist #{ihr_name}“
Aber in den geschwungenen Klammern kann man auch Ruby Ausdrücke auswerten. So gibt die Zeile
puts “1 + 1 = #{1+1}“ wie erwartet „1 + 1 = 2“ aus.
String-Operationen und Methoden
+ fügt Strings zusammen, * vervielfältigt einen String (also z.B. “A“*5 ergibt “AAAAA“).
Strings kann man als Formatierungsanweisung verwenden (str % arg wobei arg ein beliebiges Objekt
sein kann das formatiert werden kann (String, Float, Integer,…)). Beispiel: “%05d“ % 123 zeigt “00123“
an. “%-5s: %04x“ % [“ID“, 65535] zeigt “ID : ffff“ an.
.reverse (umkehren einer Zeichenkette “Hallo“.reverse -> “ollaH“), .downcase, .upcase (umwandeln
in Klein- bzw. Großbuchstaben), .length (Länge des Strings ermitteln), [n] (n(+1)-tes Zeichen des Strings),
[n..m] (n(+1)-tes bis m(+1)-tes Zeichen des Strings), [n,m] (m Zeichen vom n(+1)-ten Zeichen des
Strings), .lstrip, .rstrip, .strip (Leerzeichen links, rechts bzw. links und rechts entfernen), .to_c
(Umwandlung in Komplexe Zahl), .to_i, .to_f, .to_r (Umwandlung in Integer, Float oder Bruch (rational))
In Strings kann mit regulären Ausdrücken gesucht werden siehe
http://www.wikidorf.de/reintechnisch/Inhalt/RubyRegExpTutorial und
http://www.wikidorf.de/reintechnisch/Inhalt/RubyRegexp
Ruby – Einführung
Gesammeltes für das gemeinsame Studium
Seite 7
Arrays
Besonderheiten von Arrays in Ruby
Ruby-Arrays können jede Art von Objekt enthalten und das auch bei unterschiedlichen Typen. Also
Strings, Zahlen, weitere Arrays und gemischte Typen.
Arrays werden mit eckigen Klammern gekennzeichnet [ ]. Die Elemente im Array werden durch Komma
getrennt “,“.
Hat man ein Array deklariert (z.B. my_array = [“a“, “b“, “c“]) dann kann man mit my_array[1] das
Element des Arrays an der Position 1 welches in diesem Fall „b“ entspricht ansprechen. Arrays sind also
0-basiert (wie in vielen anderen Programmiersprachen auch).
Man kann dem Array direkt auch Werte zuweisen (my_array[1] = “x“ ) oder anhängen
(my_array << “y“). Nach diesen Aktionen ist my_array gleich [“a“, “x“, “c“ , “y“]
Array-Methoden
.inspect liefert eine Repräsentation des Arrays als String mit Delimitern die zur Analyse eines Arrays
geeignet sind.
.to_s wandelt die Elemente eines Arrays in einen String (ohne Delimiter) um ebenso wie .join jedoch mit
dem Unterschied dass man bei Join auch noch ein Trennzeichen (z.B. .join(“,“)) angeben kann. Mit
.split(“{Trennzeichen}“) lässt sich ein String auch wieder in ein Array umwandeln.
.sort liefert ein sortiertes Array als Ergebnis (funktioniert nur bei einfachen Arrays). .uniq liefert ein
Array in dem alle Doublette entfernt wurden als Ergebnis. Mit .sort! bzw. .uniq! wird die Änderung auch
ins Array übernommen (also das Array verändert). Das funktioniert sinngemäß bei vielen Ruby
Methoden so.
.delete_at(n) löscht das (n+1)-te Element aus dem Array und liefert dieses Element als Ergebnis.
.delete({Element}) löscht das Element (alle Vorkommnisse) welches als Parameter angegeben ist aus
dem Array. .delete_if(|item| block) liefert die Möglichkeit bedingten Löschens (s.u.).
<< {Element} fügt ebenso wie .push({Element}) ein Element an das Array (hinten) an während .pop das
letzte Element entfernt. Ebenso entfernt .shift das erste Element das Arrays und .unshift({Element})
fügt das Element an erster Stelle ein. .push und .unshift liefern als Ergebnis das Array, .pop und .shift das
entfernte Element zurück.
Man Kann mit Arrays auch „Rechnen“. Mit + lassen sich Elemente hinzufügen mit – entfernen wobei
jeweils (wie in Mengenoperationen) beide Operanden Arrays sein müssen, mit * (int) läßt sich ein Array
vervielfachen. Und weil wir gerade bei der Mengenlehre sind, mit & lässt sich die Schnittmenge zweier
Arrays bilden.
Mit [n] bzw. .at(n) kann das (n+1)-te Element angesprochen werden wobei wenn n negativ ist das n-te
Element von hinten zurückgeliefert wird.
.count liefert die Anzahl der Element wobei die Variante .count({Element}) die Anzahl der
Vorkommnisse des Elements und .count(|item| block) die Anzahl der Elemente zurückgeliefert wird, die
der Regel im block entsprechen (z.B. liefert bei a=[1,2,4,2] , a.count{|x| x%2==0} das Ergebnis 3
zurück.
………… u.v.m. ……….
Ruby – Einführung
Gesammeltes für das gemeinsame Studium
Seite 8
Hashes (Dictionaries)
Im Gegensatz zu Arrays sind Hashes unsortierte Objektsammlungen, die über Schlüssel zugegriffen
werden. Jeder Hasheintrag besitzt also aus einem Schlüssel und einem Objekt.
Hashes werden in geschwungenen Klammern angegeben wobei der Schlüssel und das Objekt durch =>
getrennt sind. Also z.B.
person = {‘vorname‘
=> ‘Heinz‘, ‘zuname‘ => ‘Schindelar‘, ‘wohnort‘ => ‘Baden‘ }
Mit [{Schlüsselwert}] erhält man das zum Schlüssel gehörige Objekt
(z.B. person[‘vorname‘] liefert “Heinz“ )
Sowohl der Schlüsselwert als auch das referenzierte Objekt kann ein beliebiger Objekttyp sein (Integer,
Float, String, Array,…) und das auch durchaus gemischt. An Methoden ähneln Hashes Arrays außer dass
der Zugriff über den Schlüsselwert statt über die Position erfolgt und dass Hashes nicht sortiert sind.
Hinzufügen neuer Schlüssel/Wert-Kombinationen ist jederzeit möglich. z.B. person[“geschlecht“] =
“männlich“ ergänzt den obigen Hash um einen neue Schlüssel/Wert-Kombination.
Symbole
Symbole können als Labels verwendet werden um Daten zu identifizieren (wie auch Strings, wie wir
oben gesehen haben) belegen aber weniger Speicherplatz als Strings da sie nur einmal gespeichert
werden. Achtung nicht mit Variablen verwechseln!
Symbole werden durch den Doppelpunkte gekennzeichnet und folgen darüber hinaus den Regeln der
Variablennamen. Deshalb werden sie gerne als Schlüssel in Hashes verwendet.
Wahrheitswerte (Booleans)
Booleans werden wie gewohnt in Bedingungen benutzt um Kontrollstrukturen zu steuern. Diese
Bedingungen werden durch Vergleichsoperatoren und logische Operatoren zusammengesetzt.
Die Operatoren == (ist gleich) <, >, <=, >= sind bekannt. ! ist die logische Verneinung. Daraus ergibt sich
!= für Ungleichheit. Die logischen Operatoren && (and) und || (or) sind auch üblich. Wie gewohnt ist
auch Klammerung möglich.
Es gibt aber auch eine Reihe von Boolean-Funktionen in den unterschiedlichen Objekttypen wie z.B. .nil?
für die Abfrage ob einen Variable nil (nicht definiert) ist oder .between?({Untergrenze},{Obergrenze})
für die Bestimmung ob ein Wert innerhalb gegebener Grenzen liegt oder .include?({Element}) um
festzustellen ob ein Array ein Element enthält. Gemeinsam ist diesen Funktionen typischerweise das ? in
der Funktionsbezeichnung dass auf einen Boolean-Funktion hinweist.
Folgen (Ranges)
Ranges sind Folgen von Zahlen oder Zeichen die sich aus einer einfachen Regel ergeben und wie folgt
definiert werden: {Startwert}..{Endwert} also z.B. 1..3 ergibt 1,2,3. Will man auf Ranges Methoden
anwenden muss man sie entweder Variablen zuweisen oder in runde Klammern setzen!
.begin (.first) bzw. .end(.last) zeigen den Start- bzw. Endwert der Range an. Mit dem Splat-Operator (*)
lassen sich Ranges in Arrays umwandeln. Z.B. [*(1..3)] ergibt das Array [1,2,3]
Ranges funktionieren aber nicht nur mit Zahlen sondern auch mit Zeichen (z.B. “a“..“z“) oder Strings
(“aa“..“zz“ – ja das liefert alle Kombinationen von aa,ab,ac,… bis zx, zy, zz!).
Ruby – Einführung
Gesammeltes für das gemeinsame Studium
Seite 9
Konstanten
Konstanten sind ähnlich Variablen jedoch sollen sie ihren Wert nicht während der Verarbeitung ändern.
Ruby kennzeichnet Konstanten durch einen beginnenden Großbuchstaben. Test ist also eine Konstante
während test eine Variable ist. Um Konstanten besser von Variablen unterscheiden zu können sollte
man sie vollständig mit Großbuchstaben schreiben (also TEST). Außer dass Ruby eine Warnung von sich
gibt ist jedoch das Verhalten von Variablen und Konstanten identisch.
Kontrollstrukturen
Verzweigungen (If, else elsif)
Einige Eigenheiten von Ruby sind zu beachten.
1. Es ist keine Klammerung von Anweisungen nötig.
2. Elsif ist kein Tippfehler (das e bei else if wird weggelassen)
Der Klassische Aufbau:
If Bedingung1
Anweisungen für den Fall das Bedingung1 erfüllt ist
elsif Bedingung2
Anweisungen für den Fall das Bedingung2 erfüllt ist (diese 2 Zeilen können sich beliebig oft wiederholen)
else
Anweisungen für den Fall das keine der obigen Bedingungen erfüllt ist
end
Wenn nur eine Anweisung bedingt ausgeführt werden soll kann diese Bedingung auch direkt nach der
Anweisung angegeben werden. {Anweisung] if {Bedingung}. Z.B. puts “Ja“ if 2>1 gibt „Ja“ aus
während puts “Ja“ if 2==1 keine Ausgabe erzeugt.
Varianten dieser Verzweigung ergeben sich durch
unless {Bedingung} (entspricht einem if !{Bedingung})
…
end
case {Testwert}
when Wert 1
…
when Wert 2
…
else
…
end
(entspricht dem switch in vielen Programmiersprachen)
{Bedingung} ? { Anweisungen wenn wahr} : {Anweisungen wenn falsch} (Ternärer Operator)
z.B. puts x==1 ? „eins“ : „nicht eins“
Für die optionale Zuweisung stehen 2 Varianten zur Verfügung x=y||z weist der Variablen x das Objekt y
zu wenn es existiert (true ist) ansonst das Objekt y. x||=y weist der Variablen x das Objekt y zu wenn sie
nil ist und belässt sie wenn sie nicht nil ist.
Ruby – Einführung
Gesammeltes für das gemeinsame Studium
Seite 10
Schleifen (loop do, while, until)
Hier sind wenige Überraschungen zu erwarten. Mit
loop do
…
end
wird eine (Endlos-)Schleife definiert. Um diese Schleife zu steuer gibt es die Kommandos break (Schleife
verlassen), next (den nächsten Schleifendurchlauf beginnen), redo (den aktuellen Schleifendurchlauf
neu starten), retry (den Schleifendurchlauf von neuem beginnen – von der ersten Schleife weg).
Natürlich gibt es auch die Schleifen die die Abbruchbedingung schon enthalten (while, until).
While und until arbeiten auch in einer Inlinevariante. Z.B.
X=0
puts x+=2 while x<100
Iteratoren
Iteratoren sind abzählbare Schleifen, also Schleifen mit einer bestimmten Anzahl an Durchläufen. Z.B:
5.times do
puts “Hi“
end
Andere Varianten mit demselben Ergebnis zeigen gleich einige mögliche Iteratoren:
1.upto(5) {puts „Hi“}
oder
5.downto(1) {puts „Hi“}
oder
(1..5).each {puts „Hi“}
Merke hier die Notation der Code-Blocks die jetzt nicht mit do … end sondern mit { … } erfolgt. Beide
Schreibweisen sind austauschbar.
Der Vorteil von Iteratoren ist, dass man deren Werte in den Schleifendurchläufen verwenden kann. Dies
geschieht dadurch, dass man eine Schleifenvariable in Pipes nach dem do angibt, also z.B.
5.times do |x|
puts x.to_s + “. Durchlauf”
end
Der each-Iterator ist speziell nützlich bei Arrays und Hashes, da er es ermöglicht die Elemente des Arrays
(Hashes) einzeln abzuarbeiten. Nehmen wir als Beispiel ein Array a=[1,“a“,3,7,9] so würde die
Codezeile a.each {|x| print x} die Anzeige „1a379“ und das Array als Ergebnis produzieren.
Die Kommandos break, next, redo und retry funktionieren in Iteratoren ebenso.
Code-Blocks
Was sind Code-Blocks?
Einfach gesagt sind Code-Blocks eine Gruppe von Anweisungen aber eventuell auch ein BooleanAusdruck, die durch die Schlüsselworte do und end eingefasst sind (die Kurzschreibweise { und } wird
üblicherweise nur für einzeilige Blocks verwendet). Interessant sind diese aus 2 Gründen. Erstens kann
man, wie oben gesehen, Blockvariablen verwenden, die nur innerhalb des Blocks gültig/sichtbar sind
und andererseits (und viel wichtiger) sind Blocks für viele leistungsfähige Methoden nötig.
Ruby – Einführung
Gesammeltes für das gemeinsame Studium
Seite 11
Suchen mit Hilfe von Code-Blocks
Code-Blocks werden bei verschiedenen Suchmethoden verwendet und stellen dabei i.d.R. BooleanAusdrücke dar.
.find {|var| var_Bedingung } findet das erste Vorkommnis eines Elements welches durch die Bedingung
abgebildet wird (.detect ist ein Synonym für .find). Wird nichts gefunden liefert .find nil. Z.B.:
(1..10).find {|i| i % 3 == 0) liefert den Wert 3 (der erste Wert der durch 3 teilbar ist).
.find_all {|var| var_Bedingung } findet alle Vorkommnisse eines Elements welches durch die Bedingung
abgebildet wird (.select ist ein Synonym für .find_all). Wird nichts gefunden liefert .find nil. Z.B.:
(1..10).find_all {|i| i % 3 == 0) liefert die Werte 3,6,9 (alle durch 3 teilbar).
.any? {|var| var_Bedingung } liefert ein true-Objekt wenn irgendein Element die Bedingung erfüllt
andernfalls ein false-Objekt. .all? {|var| var_Bedingung } liefert analog ein true-Objekt wenn alle
Elemente die Bedingung erfüllen.
.delete_if {|var| var_Bedingung } entfernt aus einem Array jene Elemente, die die Bedingung erfüllen.
Z.B.: [*1..10].delete_if {|i| i % 2 == 0} liefert als Ergebnis [1,3,5,7,9] zurück.
Hashes verbinden mit Hilfe von Code-Blocks
Code-Blocks können auch optional verwendet werden ein Beispiel ist die Anwendung bei der mergeMethode die bei Hashes ihre Anwendung findet.
h1.merge(h2) verbindet die Elemente zweier Hashes miteinander. Alle Schlüssel die einmalig sind,
bleiben im Ergebnis vorhanden, alle Schlüssel die doppelt vorkommen werden standardmäßig mit jenen
Werten zurückgeliefert die in h2 stehen. Dieses Standardverhalten kann durch einen Code-Block
verändert werden. So wird durch h1.merge {|key,old,new| old < new ? old : new} der jeweils
kleinere Wert zurückgegeben. Merke dass hier 3 Blockvariablen angegeben sind, die erste ist der
Schlüsselwert, die zweite der alte Wert (h1) und die dritte der neue Wert (h2). h1 und h2 bleiben in
dieser Variante unverändert. Mittels h1.merge!(h2) erhält h1 das Ergebnis der Operation zugewiesen.
Ranges, Arrays und Hashes mit Hilfe von Code-Blocks verarbeiten
Mit Hilfe der Methode .collect {|var| Anweisungen} (oder .map welches Synonym verwendet werden
kann) können Anweisungen auf ein Array (eine Range oder einen Hash) angewandt werden. Das
Ergebnis der Anweisungen wird dann als Ergebnis für jedes Element des Arrays (Ranges oder Hashes) als
Arrayelement (auch bei Ranges und Hashes) zurückgegeben. Es gilt der Grundsatz dass die Anzahl der
Elemente des Ausgangsarrays (-Ranges, -Hashes) gleich der Anzahl der Elemente des Ergebnisarrays ist.
(1..5).collect {|n| n*10}
liefert als Ergebnis [10, 20, 30, 40, 50]
liefert als Ergebnis [nil, „B“, nil] da für
die Fälle x==“a“ und x==“c“ keine Auswertung von x.capitalize erfolgt. Das gewünschte Ergebnis [“a“,
“B“, “c“] liefert hingegen [“a“, “b“, “c“].map {|x| x ==”b” ? x.capitalize : x }
[“a“, “b“, “c“].map {|x| x.capitalize if x ==”b”}
Im Falle der Anwendung bei Hashes ist zu beachten dass 2 Blockvariablen (Schlüssel und Wert)
übergeben werden. Z.B.
h = {:a => 1, :b => 2 }
h.map {|k, v| "#{k}: #{v*10}"}
liefert als Ergebnis das Array mit den 2 Elementen ["a: 10", "b: 20"]
Ruby – Einführung
Gesammeltes für das gemeinsame Studium
Seite 12
Sortieren mit Hilfe von Code-Blocks
Mit dem Vergleichsoperator <=> (dem sog. Spaceship-Operator)
können 2 Objekte verglichen werden. Als Ergebnis des
Vergleiches gibt der Vergleichsoperator 3 mögliche Werte
zurück.
Wert 1 <=> Wert 2
Wert 1 kleiner Wert 2
Wert 1 gleich Wert 2
Wert 1 größer Wert 2
Ergebnis
-1
0
1
Die .sort-Methode sortiert mit Hilfe dieses Operators. Man kann aber die Standardsortierung durch
Codeblocks modifizieren. Die Sortierung für numerische Werte ist aufsteigend.
array.sort und array.sort {|v1, v2| v1 <=> v2} sind gleichwertig. Will man die Sortierung
umkehren kann man dies auf 2 Arten: array.sort.reverse oder array.sort {|v1, v2| v2 <=> v1}.
Die Standardsortierung von Strings ist alphabetisch aufsteigend. Will man jedoch Strings z.B. nach ihrer
Länge sortieren hilft nur noch ein Code-Block.
obst = [“pfirsiche”, “bananen”, “birnen”]
obst.sort {|f1, f2| f1.length <=> f2.length} liefert [“birnen”, “bananen”, “pfirsiche”]
Aber es wäre nicht Ruby gäbe es dafür nicht auch einen kürzeren Weg: obst.sort_by {|f| f.length}
Werte akkumulieren mit Hilfe von Code-Blocks
Die Methode .inject {|memo,n| Operation mit memo und n} ermöglicht das akkumulieren von Werten
über ein Array (Range, bedingt Hash). Memo fungiert dabei als Akkumulatorvariable deren Endwert dem
Ergebnis der inject-Operation entspricht.
(1..5).inject {|m,n| m+n} liefert das Ergebnis 15 (=1+2+3+4+5). Der Startwert von memo ist
standardmäßig 0 kann aber mit .inject(Startwert) auch auf einen anderen Wert gesetzt werden. Wie
gewohnt funktioniert die Akkumulation auch mit anderen Datentypen als numerischen. z.B.:
("aa".."af").inject {|m,n| m+n} liefert "aaabacadaeaf"
Achtung, auch hier muss in jeder Iteration ein gültiger mit der Operation kompatibler Wert ermittelt
werden (siehe collect).
Methoden
Definition uns Aufruf von Methoden
def methodenname
(… Code der Methode)
end
… definiert eine Methode mit dem Namen „methodenname“ wobei aus Kleinbuchstaben besteht.
Methoden werden üblicherweise in eigenen Files mit der Endung .rb abgelegt. Sowohl in irb als auch in
anderen Files kann mittels require „Filename“ die Methodendefinition geladen werden (auf Pfad
achten). Methoden müssen im Code vor deren Benutzung definiert sein (also in einer früheren Zeile).
Methoden werden einfach über ihren Methodennamen aufgerufen.
Definition von Argumenten für Methoden
Argumente werden einfach als durch Komma getrennte Variablenliste optional mit einem Defaultwert
versehen hinter dem Methodennamen in Klammern angeführt. Z.B.
def addiere (n1, n2=0)
puts n1 + n2
end
Ruby – Einführung
Gesammeltes für das gemeinsame Studium
Seite 13
Definition von Rückgabewerten in Methoden
Methoden liefern automatisch das Ergebnis der letzten Operation der Methode als Return-Value. Will
man das übersteuern oder explizit kennzeichnen kann man die Anweisung return Rückgabewert
angeben. Dies führt auch automatisch zur Beendigung der Methode.
Will man mehrere Rückgabewerte in einer Methode realisieren, so kann man dies über ein Array als
Rückgabewert verwirklichen. Z.B.:
def add_and_sub (n1=0, n2=0)
return [n1+n2, n1-n2]
end
Eine nette Eigenschaft von Ruby ermöglicht es das rückgegebene Array (welches im obigen Beispiel aus
2 Rückgabewerten besteht) auch gleich mehreren Variablen (hier 2) zuzuordnen. Z.B.:
add, sub = add_and_sub(10,7)
Nach dieser Zeile enthält add den Wert 17 und sub den Wert 3.
Operationen sind auch Methoden
Wenn wir eine Operation betrachten müssen wir beachten, dass diese ebenso Methoden sind. 10 + 2 ist
eigentlich 10.+(2) also die Methode + des Integer-Objekts 10 mit dem Parameter 2. Dies gilt ebenso für
-, *, /, %, <<, [], usw. Interessant ist das bei einem Array. Die Zuweisung array[2]=“x“ ist eigentlich so zu
lesen die Methode []= wird auf das Array array angewandt mit den Parametern 2 und „x“ also
array.[]=(2,“x“). Ruby versteht aber das für uns wesentlich besser lesbare Format array[2]=“x“ und
wandelt es intern in die oben gezeigte Form um.
Genau dieses Verhalten bezeichnet man als Syntactic Sugar!
Klassen
Definition und Instanzierung von Klassen
class Klassenname
…
end
Die Definition von Klassen erfolgt sehr ähnlich Methodendefinitionen jedoch mit dem Schlüsselwort
class und (wichtig!) einem Klassennamen der mit einem Großbuchstaben beginnt (mehrere Wörter
werden durch die CamelCaseSchreibweise getrennt).
Innerhalb von Klassen lassen sich wie gewohnt Methoden definieren die dadurch zu Klassenmethoden
werden.
Klassen werden instanziert durch die Methode new. Um mit Objekten arbeiten zu können müssen sie
Variablen zugewiesen werden. Die typische Form ist variable = Klasse.new
Definition von Attributen in Klassen
Instanzvariablen werden durch das @ Symbol gekennzeichnet und sind in Klassen gekapselt, können
also ausschließlich über Methoden zugegriffen werden (Setter und Getter). Z.B.:
class Person
def set_name(name)
@name = name
end
def get_name
@name
end
end
Ruby – Einführung
Gesammeltes für das gemeinsame Studium
Seite 14
Um nun eine Instanzvariable zu setzen muss man in unserem Beispiel (nachdem man mit person =
Person.new eine Instanz generiert hat) die Methode person.set_name(„Franz Meier“) aufrufen. Um
den Wert zu erhalten gibt man z.B. puts person.get_name an. Um das Verhalten natürlicher zu
gestalten kann man auch die Getter und Setter Methoden komfortabler definieren (Syntactic Sugar):
class Person
def name=(name)
@name = name
end
def name
@name
end
end
Nun kann man (nach Instanzierung) mit person.name=”Franz Meier” die Setter-Methode aufrufen wie
wenn man auf das Attribut direkt zugreifen könnte.
Und erwartungsgemäß funktioniert nun auch puts person.name
Und es wäre nicht Ruby wenn das nicht auch noch kürzer ginge. Und hier ist es:
class Person
attr_accessor :name
end
Will man nur eine Getter-Methode schreibt man attr_reader :name, will man nur eine SetterMethode schreibt man attr_writer :name. Und natürlich kann man auch mehrere solche
Instanzvariablenmethoden auf einmal definieren, z.B.: attr_accessor :name, :plz, :ort, :strasse
Initialisierungsmethoden
Wird in einer Klasse eine Methode mit dem Namen „initialize“ definiert so wird diese automatisch
bei der Instanzierung des Objekts aufgerufen. Enthält diese Methode Parameter können diese mittels
Angabe der Parameter beim Aufruf von „new“ übergeben werden.
Klassenmethoden und -attribute
Eine Klassenmethode ist eine Methode die auf der Ebene einer Klasse und nicht auf der Ebene eines
Objekts (einer Instanz der Klasse) aufgerufen wird. Die bekannteste Klassenmethode ist „new“.
Eine Klassenmethode wird genauso definiert wie eine normale Instanzmethode jedoch wird vor dem
Methodennamen der Ausdruck „self.“ angeführt. Der Zusatz self kennzeichnet in jedem
Anwendungsfall das gerade instanzierte Objekt (innerhalb einer Instanzmethode) oder die Klasse selbst
(im Fall der Methodendefinition und innerhalb von Klassenmethoden). Klassenmethoden werden für
Aufgaben benutzt, die unabhängig von den Instanzen bzw. über mehrere Instanzen der Klasse gehen.
Will man Informationen über die Klasse in einer Variablen speichern benutzt man Klassenvariablen die
durch das Präfix „@@“ gekennzeichnet werden. Initialisiert werden diese Variablen typischerweise am
Beginn einer Klasse noch vor den Klassen- und Instanzmethodendefinitionen einfach durch ´Zuweisung
des Initialwertes. Z.B. @@anz_instanzen = 0
Verwendet werden die Klassenvariablen wie normale Variablen mit dem Unterschied, dass es sie nur
einmal pro Klasse gibt. Z.B. (für das Zählen von Instanzen)
def initialize
@@anz_instanzen += 1
end
Ruby – Einführung
Gesammeltes für das gemeinsame Studium
Seite 15
Für Klassenvariablen gilt dasselbe wie für Instanzvariablen, auf sie kann nur mit Hilfe von Methoden
zugegriffen werden. Diese werden als Klassenmethoden (mit self.) definiert und genauso wie die Getter
und Setter bei den Instanzvariablen gestaltet. Leider gibt es in Core-Ruby derzeit noch keine
Kurzvariante wie bei den Instanzvariablen (in Ruby on Rails gibt es cattr_accessor). Da aber
Klassenvariablen seltener vorkommen ist dies nicht so tragisch. Unser Beispiel sieht demnach also wie
folgt aus:
def self.anz_instanzen
@@anz_instanzen
end
def self.anz_instanzen=(wert=0)
@@anz_instanzen = wert
end
Vererbung
Wie in objektorientierten Programmiersprachen üblich kann man Klassen (Kind- oder Subklassen) von
anderen Klassen (Eltern- bzw. Superklassen) ableiten. Dadurch übernimmt die Subklasse alle
Eigenschaften der Superklasse. Subklassen werden wie folgt definiert:
class subklasse < superklassse
Im Unterschied zu vielen anderen objektorientierten Programmiersprachen unterstützt Ruby keine
Mehrfachvererbung (das gewünschte Verhalten kann jedoch mit Modulen weitgehend simuliert
werden).
Subklassen können jede Methode der Superklasse überschreiben in dem einfach eine neue Definition
einer Methode angeführt wird. Die jeweils letzte Definition in sequentieller Abfolge zählt. Dieses
Verhalten gilt auch für Klassen. Es können also Klassendefinitionen immer wieder neu geschrieben
werden und dadurch auch überschrieben werden. Das funktioniert sogar bei Ruby-Core Klassen. Ein
Beispiel: wir starten irb –simple-prompt
>> X = [1,2,3]
=> [1, 2, 3]
>> x.to_s
=> „123“
Das ist das Standardverhalten. Nun schreiben wir die originale to_s Methode der Array-Klasse um:
>> class Array
>> def to_s
>>
self.join(‘,‘)
>> end
>> end
=> nil
>> x.to_s
=> “1, 2, 3”
Eine sehr leistungsfähige Sache!
Möchte man in einer Subklasse die Methode umschreiben aber auf die Methode der Superklasse
zugreifen verwendet man „super“, welches die entsprechende namensgleiche Methode der Superklasse
aufruft.
Ruby – Einführung
Gesammeltes für das gemeinsame Studium
Seite 16
Module
Namensräume
Module sind ähnlich wie Klassen Hüllen um eine Menge Programmcode können aber im Gegensatz zu
Klassen nicht instanziiert werden. Module werden oft im Zusammenhang mit Klassen verwendet, da sie
zur Definition von Namensräumen (namespaces) verwendet werden können und dadurch ermöglichen
Namenskonflikte (von eventuell gleichnamigen Klassen in unterschiedlichen Bibliotheken) zu
verhindern.
Der Namensraum wird einfach dadurch definiert, dass die Klasse in ein Modul „eingepackt“ wird. Etwa
so:
module Modulname
class Klassenname
….
end
end
Zugegriffen wird auf die Klasse dann mit Modulname::Klassenname
Mixins
Da es in Ruby keine Mehrfachvererbung gibt, verwendet man Module (sogenannte Mixins) zur
Realisierung mehrfach verwendeter Codeelemente. Der durch ein Modul definierte Codebereich wird
mit der Anweisung include Modulname an der Stelle im Code eingefügt an der die Includeanweisung
steht.
Diese Module eigenen sich auch bestens als Code-Bibliotheken. In diesem Fall sind die Anweisungen
load und require zu erwähnen. Load dient dazu solche Bibliotheken zu einem bestehenden Code dazu zu
laden (jedes mal wenn load aufgerufen wird). Wenn man dies aber öfters tut ist das
Speicherplatzverschwendung. Require funktioniert ähnlich, jedoch lädt es das File nur einmal in den
Speicher und kann feststellen ob ein File schon geladen ist. Beide Anweisungen haben die Form:
load/require ‘Pfad zu Rubycodedatei‘
Sie liefern true wenn eine Datei geladen wurde, andernfalls false.
Filehandling
Grundlagen Input/Output
Einfache Ausgabemethoden haben wir ja schon kennen gelernt:
puts … gibt was immer man danach angibt als Ausgabe aus inklusive einem Zeilenvorschub.
print … macht dasselbe jedoch ohne Zeilenvorschub.
Die einfachste Eingabemethode ist gets. Mit gets wartet Ruby auf eine Eingabe des Benutzers und
liefert diese als Ergebnis der gets-Methode zurück. Beachte, dass das Ergebnis auch das
Zeilenvorschubzeichen (in der Regel „\n“) enthält. Um dieses zu entfernen kann man die Methode
chomp verwenden. Eine typische Eingabe sieht also wie folgt aus:
mein_input = gets.chomp
Diese Methoden sind auch anwendbar beim Umgang mit Files. Dazu gibt es in Ruby die IO-Klasse und
deren Subklasse File.
Ruby – Einführung
Gesammeltes für das gemeinsame Studium
Seite 17
Filesystem: mögliche Probleme in Cross-Platform-Environments
Übliche Probleme beim Umgang mit dem Filesystem betreffen „Cross-Platform“-Unterschiede. Diese
betreffen in der Regel Seperatoren und Zugriffsrechte.
Die Seperatoren zwischen den Directories in Windows- (\) bzw. Linux-basierten (/) Systemen sind
unterschiedlich. Unter Ruby verwendet man in der Regel den Forwardslash (/) der auch unter
Windowssystemen richtig interpretiert wird.
Besser ist jedoch die Nutzung der File.join-Methode in der einfach alle Bestandteile des Pfades als
Parameter angegeben werden. Z.B.: File.join(“ruby“, “myprogs“, “myfile.rb“)
unter Linux(MacOSx, ..) wird daraus ruby/myprogs/myfile.rb
und unter Windows wird daraus ruby\myprogs\myfile.rb
Will man einen absoluten Pfad erhalten so gibt man als ersten Bestandteil eine Leeren String ““ an
z.B. File.join(“ruby“, “myprogs“, “myfile.rb“) erzeugt unter Windows
\ruby\myprogs\myfile.rb
Beim lokalen Arbeiten mit Files wird es in der Regel keine Probleme geben, da man hier meist Owner ist
und alle Rechte (Lesen, Schreiben, Ändern, Löschen, Ausführen, etc.) besitzt. In Netzwerken ist dies
häufig nicht so weswegen hier auf die Rechte und Eigentümerschaft geachtet werden muss. Unter
Windows-Systemen wir dies über das Eigenschaftenfenster der Dateien oder ab Windows Vista über die
Commandline-Befehle Takeown.exe (wenn Administratorrechte erteilt werden sollen auch noch
icacls.exe) und cacls.exe. Unter Unix-basierten Systemen heißen die entsprechenden Kommandos
chown bzw. chmod.
Grundlegendes zu Filepfaden
Wie gewohnt können in Ruby-Programmen relative und absolute Pfade verwendet werden. Bei relativen
Pfaden gibt „./“ Das aktuelle Directory und „../“ das übergeordnete Directory an.
Um festzustellen welches der aktuelle Pfad ist stellt Ruby die Konstante __FILE__ zur Verfügung, die
den Filenamen des aktuellen Files enthält.
Um nun den absoluten Pfad des aktuellen Files zu erhalten gibt man FILE.expand_path(__FILE__) an
und bekommt diesen inklusive Dateinamen zurückgeliefert.
Will man nur das Directory des aktuellen Files so gibt man File.dirname(__FILE__) an. Dieses liefert
den relativen Pfad des angegebene Files den man als Ausgangspfad für alle Fileoperationen verwenden
kann.
Hinweis: Enthält der Pfad ein Leerzeichen muss dieses mit \ markiert werden aus dem Directory “mein
file“ wird “mein\ file“ (Achtung Doppelte Anführungszeichen sind hier wichtig!).
Dateizugriff
Mit File.new wird ein neues File-Objekt angelegt und auch gleichzeitig das File auf dem Speichermedium
angelegt. Die übliche Form der File.new-Methode hat folgende Struktur:
myfile = File.new (‘Dateiname‘,‘Modus‘)
# Hier kommen die Fileoperationen
myfile.close
Alternativ kann man auch die File.open verwenden (ist übersichtlicher und mehr Ruby-like)
File.open (‘Dateiname‘,‘Modus‘) do |myfile|
# Hier kommen die Fileoperationen
end
Ruby – Einführung
Gesammeltes für das gemeinsame Studium
Seite 18
Die Modi beim Filezugriff sind:
r
w
a
Lies vom Start weg (Datei muss existieren)
(Über-)schreib File vom Start (legt neues File an)
Schreibt Daten an das Ende eines bestehenden Files
r+
w+
a+
Lesen und Schreiben (vom Start weg)
Lesen und Schreiben (destruktiv)
Lesen und Schreiben (am Ende)
Schreiben von Dateien
Um auf Dateien zu schreiben kann man die schon bekannten Methoden puts (mit Zeilenvorschub) und
print (ohne Zeilenvorschub verwenden, die man einfach als Methoden des instanziierten Files aufruft.
myfile.print “abcdefg“
myfile.puts “BLABla“
Beide Methoden liefern als Ergebnis das nil-Objekt zurück. Es gibt aber noch 2 weitere Varianten wie
man in Dateien schreiben kann:
… entspricht print liefert aber als Ergebnis die Anzahl der geschriebenen
Myfile.write „abcdefg“
Zeichen zurück
myfile << „abcdefg“ … entspricht ebenfalls print liefert aber als Ergebnis das File-Objekt zurück
Lesen von Dateien
Lesen von Dateien ist ebenfalls mit der schon bekannten Methode gets möglich:
zeile = myfile.gets
Die Methode gets liest dabei alle Zeichen bis zum nächsten Zeilenumbruch. Achtung der Zeilenumbruch
ist in zeile enthalten und sollte daher mit der chomp.Methode entfernt werden. Da man jedoch beim
Ende der Datei als Ergebnis der gets-Methode nil zurückgeliefert bekommt und nil die chomp-Methode
nicht kennt sollte man eine Überprüfung einbauen, etwa:
zeile = (zeile==nil)
? ““ : zeile.chomp
Oder mit einer Leseschleife verbunden:
File.open (‘file.txt‘,‘r‘) do |myfile|
while line = myfile.gets
puts line.chomp
end
end
<- Diese Schleife wird durchgeführt solange file.gets ungleich nil ist
<- erst hier chomp da jetzt sicher ein Text in line ist
Will man jede Zeile einer Datei lesen so gibt es auch eine kürzere Schreibweise für obiges Beispiel:
File.open (‘file.txt‘,‘r‘) do |myfile|
myfile.each_line {|line| puts line.chomp }
end
Eine weitere Möglichkeit aus Dateien zu lesen ist die read-Methode mit der man die als Parameter
übergebene Zahl an Zeichen aus der Datei lesen kann myfile.read(10) liest die nächsten 10 Zeichen
der Datei. Achtung: Auch Zeilenvorschübe (\n) werden mitgezählt.
Der Filepointer
Will man gezielt in Dateien schreiben oder aus ihnen Lesen benutzt man den Filepointer, der ähnlich
dem Cursor in einer Textverarbeitung die aktuelle Position in der Datei anzeigt. Beachte dass bei
Schreiboprationen die Zeichen an der aktuellen Position überschrieben werden und nicht eingefügt.
Mit myfile.pos kann man die aktuelle Position des Filepointers bestimmen (das erste Zeichen hat die
Position 0) und mit myfile.pos = 10 kann man z.B. den Filepointer auf das 11. Zeichen setzen. Springt
Ruby – Einführung
Gesammeltes für das gemeinsame Studium
Seite 19
man auf eine Position, die im File nicht enthalten ist erfolgt keine Fehlermeldung. Read bzw. gets liefert
dann nil als Ergebnis und write (etc.) fügt bis zur Position nill-Charakter ein .
myfile.rewind entspricht myfile.pos = 0. Außerdem setzt rewind die lineno auf 0. Was ist lineno?
Mit der Methode lineno kann ein interner Zähler der durch die gets (und die readline)-Methode bei
jedem Aufruf um 1 erhöht wird, abgefragt werden. Benutzt man konsequent gets zum Einlesen der
Daten entspricht lineno der Zeilennummer (bei 0 beginnend).
myfile.eof? prüft ob das Ende der Datei erreicht ist.
Umbenennen, Löschen und Kopieren von Dateien
Dazu dienen einfach die 2 Methoden File.rename (mit 2 Parametern: alter Name, neuer Name) und
File.delete (mit dem Filenamen als Parameter). Wichtig ist dabei zu beachten, dass man für die
Operationen auf der Dateiebene die nötigen Berechtigungen hat.
Will man Files kopieren muss man zuerst mit require eine Standardbibliothek einbinden.
Require ‘fileutils‘
FileUtils.copy(‘from_file.txt‘,‘to_file.txt‘)
Die FileUtils-Klasse hat neben der copy-Methode (kurz cp) auch noch eine Move- (kurz mv-) und eine
remove-(rm-)Methode. Außerdem sind die meisten Unix-Commandos über FileUtils zugänglich (cd,
mkdir, rmdir, chmod, chown, pwd, ln, touch).
Weitere Operationen mit Files und Directories
File.exists?(myfile) … liefert true wenn das File (oder Directory) existiert
File.file?(myfile) … liefert true wenn myfile ein File (und z.B. kein Directory) ist
File.directory?(myfile) … liefert true wenn myfile ein Directory ist
File.readable?(myfile) … liefert true wenn myfile ein File ist, das gelesen werden kann
File.writeable?(myfile) … liefert true wenn myfile ein File ist, das geschrieben werden kann
File.executeable?(myfile) … liefert true wenn myfile ein File ist, das ausgeführt werden kann
File.size(myfile) … liefert die Dateigröße in Byte
File.mtime(myfile) … liefert die Zeit zurück an der die Datei zuletzt modifiziert wurde
File.atime(myfile) … liefert die Zeit zurück an der die Datei zuletzt zugegriffen (gelesen oder
geschrieben) wurde
File.ctime(myfile) … liefert die Zeit zurück an der die Datei zuletzt ihren Status änderte (gelesen,
geschrieben oder eine Veränderung bei Eigentümer, Gruppe oder Rechten erfuhr)
All diese Methoden sind über das stat Objekt innerhalb einer Instanz der Klasse File ebenfalls verfügbar.
File.size(myfile) entspricht also myfile.stat.size.
Die Dir-Klasse eröffnet uns den Zugriff auf Directories. Mit Dir.foreach(‘.‘) {|entry| puts entry}
bekommen wir beispielsweise eine Liste aller Dateien und Subdirectories des aktuellen Directories.
Ruby – Einführung
Gesammeltes für das gemeinsame Studium
Grafiklibraries
1. TK, evtl. GTK, evtl. FXRuby
Seite 20
Ruby – Einführung
Gesammeltes für das gemeinsame Studium
Codebeispiele
Primzahlensieb:
print "Primzahlen bis:"
g=STDIN.gets
x=(2..g.to_i).to_a
y=[]
while x.count > 0 do
y << x.shift
x.delete_if { |i| i % y.last == 0}
end
y.each { |i| print i.to_s + ", " }
Seite 21
Herunterladen