Open Source im professionellen Einsatz
Linux-Magazin 06/2001

Objektorientierte Skriptsprache Ruby

Roter Stern

Ruby ist eine objektorientierte Skriptsprache, die sich einen Platz zwischen den etablierten Sprachen Perl, Python und vielleicht auch PHP erobert. Ruby, eine Entwicklung aus Japan, hat auch einen gewissen Unterhaltungswert, was den Einstieg erleichtert.

1177

Aus Japan, dem Land der aufgehenden Sonne, kommt ein neuer Stern am Himmel der Skriptsprachen. Aber braucht die Welt eine neue Skriptsprache? Gibt es doch bereits etablierte wie Perl, Python, Tcl und viele mehr. Ruby ist ein neuer Ansatz für eine durchdachte und objektorientierte Skriptsprache, die leicht zu benutzen ist.

Da sie recht jung ist, sind noch nicht so viele Libraries wie für Perl oder Python vorhanden, dennoch ist sie bereits für viele Zwecke voll einsetzbar. Dieser Artikel führt an einigen Beispielen die Konzepte vor und zeigt, wie kompakt, aber dennoch sauber strukturiert Ruby sein kann.

Eierlegende Wollmilch-Sprache?

Ruby wurde 1993 bis 1995 von Yukihiro (Matz) Matsumoto in Japan entwickelt; Perl 4 und Python gab es bereits. Während Python eine Hybridsprache mit Funktionen für prozedurale Programmierung und mit Objekten für die OO-Programmierung ist, ist Ruby rein objektorientiert: Es gibt keine Funktionen, nur Methoden - und alles ist ein Objekt. Dabei gibt es einen Ersatz für Funktionen: Eine außerhalb einer Klasse definierte Methode wird zu einer privaten Methode der Überklasse Object, wodurch sie überall verfügbar wird.

Die Syntax und die Designphilosophie sind stark an Perl angelehnt, so gibt es Statement Modifiers ( if, unless, while und weitere ), eingebaute reguläre Ausdrücke, Sondervariablen wie $_ sowie den Unterschied zwischen "..." und '...'-Strings. Ruby bedient sich also bei diversen Programmiersprachen und vereinigt sie in einer neuen.

Im Gegensatz zu Perl bezeichnen $, @ und % nicht unterschiedliche Datentypen, sondern den Scope einer Variablen: Normale Variablen kommen völlig ohne Zeichen wie $, % oder @ aus, $var bezeichnet eine globale Variable beliebigen Typs und @var eine Instanzvariable beliebigen Typs in einem Objekt. Semikola am Zeichenende gibt es in Ruby-Programmen nicht.

Objektorientiert

Wie bei allen OO-Sprachen auch stehen in Ruby praktische Standardklassen zur Verfügung, die sich leicht einsetzen lassen. Natürlich kann man auch selbst Klassen definieren, inklusive Vererbung sowie privater, geschützter und öffentlicher Methoden. Die Objektorientierung von Ruby geht allerdings noch ein ganzes Stück weiter, so ist kurz gesagt eigentlich alles, was sich modifizieren lässt, eine Instanz einer Klasse (beziehungsweise eine Referenz darauf).

Das gilt auch schon für ganz normale Zahlen, so ist beispielsweise -42 eine Instanz der Integerklasse und verfügt somit auch über die in der Integerklasse definierten Methoden. Durch diese bis zu den Basiselementen reichende Objektorientierung erhält man Informationen über eine Zahl oder einen String nicht durch eine Funktion wie etwa sizeof(scalar) oder int2str(int), sondern direkt vom Objekt, eben durch eine seiner Methoden.

Um beispielsweise die String-Repräsentation von 42 zu erhalten, kann man die Methode 42.to_s aufrufen. Das ist natürlich ein banales Beispiel, jedoch ist die (überschreibbare) Methode .to_s bereits in der Klasse Object definiert, der Mutter aller Klassen, und somit in absolut jeder Klasse - auch den eigenen - verfügbar.

Neben den üblichen Klassen- und Instanzmethoden bietet Ruby die Möglichkeit, so genannte Iteratoren zu nutzen. Das sind Methoden, die über die einzelnen Elemente eines Objektcontainers iterieren, also über die Elemente eines Arrays, eines Hashes, die Zeilen einer Textdatei oder auch einer eigenen Containerklasse.

Sogar die Integerklasse, selbst eigentlich kein Container, verfügt über hilfreiche Iteratoren wie etwa .upto(num) oder .downto(num), die ausgehend vom Objekt in Einerschritten bis num iterieren. Dabei übergibt man dem Iterator einen Funktionsblock, der der Reihe nach für jedes Element aufgerufen wird.

Um zu zeigen wie das geht, betrachten wir ein kleines Codebeispiel, bei dem der .upto-Iterator von Integer zum Einsatz kommt, um für die Zahlen von Eins bis Zehn eine Ausgabe zu erzeugen:

#!/usr/bin/ruby
Max = 10    # Konstante
1.upto(Max) do
 |i|       # iteriertes Element
 print  "#{i} ^2 = ", i*i, "n"
end

In der ersten Zeile definieren wir eine Konstante Max, deren Name mit einem Großbuchstaben beginnt, .upto ist der bereits erwähnte Iterator, der hier von 1 bis Max iteriert. do und end schließen den Codeblock ein, der an den Iterator übergeben wird. Alternativ kann man den Block auch mit { und } einklammern. |i| weist das Element der aktuellen Iteration der Variablen i zu, die print-Zeile gibt schließlich i und i*i aus.

Beachten Sie, dass normale Variablen mit einem Kleinbuchstaben beginnen müssen und Konstanten mit einem Großbuchstaben. Falls Ihnen der Einwand auf der Zunge liegt, dass for viel universeller ist, gebe ich Ihnen Recht. Da man jedoch in neun von zehn Fällen mit einem Inkrement von eins rauf- oder runterzählt, ist die upto-Methode (und downto, step und andere) ein echter Gewinn.

Wie wir gleich an einem etwas komplexeren Beispiel sehen werden, erlauben Iteratoren auch in vielen anderen Fällen eine sehr effiziente Programmierung. Betrachten Sie aber vorher noch einmal die Zeile Max = 10. Wir sollten uns noch einmal vergegenwärtigen, dass hier die 10 nicht einfach eine Zehn ist, sondern eine Instanz der Integerklasse.

Der Zuweisungsoperator erzeugt eine neue Instanz und weist Max schließlich eine Referenz darauf zu. Betrachten wir eine etwas realere Problemstellung: Sie wollen im aktuellen Verzeichnis alle Dateien, die auf .MP3 enden, so umbenennen, dass sie auf .mp3 enden. Da das mv-Kommando von Linux bei diesem alltäglichen Problem kaum eine Hilfe ist (außer Sie sprechen fließend Bash), bauen wir uns ein Skript in Ruby.

Die Aufgabe: Man hat ein Verzeichnis, will den Inhalt auslesen und je nach Beschaffenheit des Eintrags die Datei umbenennen. Während man sich in Perl mit Funktionen wie opendir und readdir herumschlagen muss, kann man das Problem in Ruby genau so lösen, wie wir es formuliert haben: Man nimmt ein Dir-Objekt, lässt sich die Einträge geben und benennt gegebenenfalls Dateien um.

Betrachten Sie also den folgenden Code:

Dir.open(".").entries.each do
 |entry|
 neu = entry.gsub(/.MP3$/, ".mp3");
 File.rename(entry,neu) if neu != entry
end

Das ist doch recht übersichtlich: Dir.open liefert eine neue Instanz der Klasse Dir, die wir nicht einer Variablen zuweisen, sondern direkt weiterverwenden. Die entries-Methode der Dir-Instanz liefert ein Array mit allen Verzeichniseinträgen in Form von String-Objekten, each schließlich ist der Standard-Iterator über alle Elemente eines Containers (hier: Arrays). Alle Elemente des Arrays landen nacheinander in der Variablen entry. Die Stringmethode gsub ersetzt .MP3 durch .mp3 und das Ergebnis landet in der Variablen neu. Die letzte Zeile schließlich benutzt die Klassenmethode rename der Klasse File, um gegebenenfalls eine Umbenennung vorzunehmen.

Klassenmethoden lassen sich im Gegensatz zu Instanzmethoden ohne vorhandene Instanz einer Klasse aufrufen. Das angehängte if expr ist ein von Perl her bekanntes Konstrukt, bei dem sich mitunter die Nackenhaare sträuben. Man hätte natürlich ein normales dreizeiliges Konstrukt if, Kommandos, end einsetzen können, jedoch ist die gewählte Schreibweise vor allem bei einzeiligen if-Blöcken oftmals übersichtlicher.

Auch wenn das Beispiel im ersten Moment befremdlich gewirkt haben mag, orientiert sich die Realisierung doch sehr daran, wie man denkt - und entsprechend schnell gewöhnt man sich an diese Art zu programmieren. Erwähnt sei hier noch die Möglichkeit, kleine Programme on the Fly mit dem -e `...`-Parameter an den Interpreter zu übergeben. Dann muss man allerdings die einzelnen Kommandos durch Semikola trennen.

Linux-Magazin kaufen

Einzelne Ausgabe
 
Abonnements
 
TABLET & SMARTPHONE APPS
Bald erhältlich
Get it on Google Play

Deutschland

Ähnliche Artikel

  • Ruby

    Vom einzeiligen Kommando über maßgeschneiderte Skripte bis zum ausgewachsenen Konfigurationsmanager: Die freie Programmiersprache Ruby erweist sich als praktisches Schmuckstück für die Systemadministration und erledigt vieles in erstaunlich wenigen Zeilen.

  • Ruby 1.9.2 ist fertig

    Die neueste stabile Version der 1.9-Serie bringt Anwendern neben neuen Funktionen auch einige inkompatible Änderungen.

  • Mischmasch

    Ruby on Rails spaltet die Gemeinde der Webentwickler. Für die einen der Weisheit letzter Schluss, für die anderen der größte Hype aller Zeiten. JRuby bringt beide Fronten wieder an einen Tisch.

  • Unsichere Strings in Ruby on Rails
  • Ruby spricht viele Sprachen

    Domain Specific Languages vereinfachen die textbasierte Arbeit am Computer durch eine zusätzliche Abstraktionsstufe. Statt jedes Detail in einer allgemeinen Sprache auszuprogrammieren, genügen wenige Schlüsselwörter. Ruby enthält die nötigen Ausdrucksmittel für solche Vereinfachungen.

comments powered by Disqus

Ausgabe 01/2017

Digitale Ausgabe: Preis € 6,40
(inkl. 19% MwSt.)

Artikelserien und interessante Workshops aus dem Magazin können Sie hier als Bundle erwerben.