Ruby-Programmierung: Kommandozeilenintegration

Zurück zum Inhaltsverzeichnis.

Auch wenn das Arbeiten auf der Kommandozeile in den Hintergrund gerückt ist, so macht es dennoch für viele kleine Anwendungen Sinn mit den Beschränkungen, aber auch der Einfachheit der Kommandozeile zu leben. Die Programmierung von User Interfaces ist aufwendig und man stößt auf viele Tücken. Was auf der Kommandozeile ein einfaches gets ist, ist bei UIs das Handhaben von Tastatureingaben, Mausbewegungen und so weiter. Insbesondere auf Linuxsystemen ist das Arbeiten mit Kommandozeilenprogrammen weiter verbreitet, was man schon daran sieht, dass man ein skript.rb nicht via Doppelklick ausführt, sondern man auf der Kommandozeile den Rubyinterpreter aufruft.

Kommandozeilenparameter

Bearbeiten

Wenn man sich genauer Gedanken darüber macht, was die Zeile ruby skript.rb bedeutet, dann gelangt man zu der Erkenntnis, dass das Ruby in Abhängigkeit von den nachfolgenden Zeichen unterschiedliche Funktionen erfüllt. Entweder interpretiert es ein Skript, gibt eine Hilfe aus (-h) oder die Version (-v). Dieses Verhalten erinnert stark an Methodenparameter, bei denen wir Fallunterscheidungen bei Parametern schon kennengelernt haben und ähnlich funktionieren auch Kommandozeilenparameter. Die Parameter werden auf der Kommandozeile mit Leerzeichen voneinander getrennt und sind im Skript im konstanten Array ARGV verfügbar.

puts ARGV.length
----

Das Array enthält dabei immer Strings, gegebenenfalls ist also eine Typumwandlung nötig.

Zur Kommandozeile zurück

Bearbeiten

Neben dem Erhalten von Parametern gibt es die Möglichkeit, das System direkt aus Ruby anzusprechen. Dazu gibt es zwei unterschiedliche Möglichkeiten: Der Aufruf der Methode system erhält als Parameter einen String, der ausgeführt wird, als ob er sich auf der Kommandozeile befände. system erzeugt dazu einen neuen Prozess, daher ist es nicht ohne weiteres möglich auf das Ergebnis dieses Systemcalls zuzugreifen.

Möchte man das tun, ist es möglich einen Systemaufruf mit `...` oder %x(...) auszuführen. Beide Möglichkeiten geben die Standardausgabe des ausgeführten Codes als String zurück, daher ist möglich diesen im eigenen Programm weiter zu verwenden. Dadurch ist es sehr einfach andere Programme um Funktionalität zu erweitern, oder eine grafische Oberfläche für ein Kommandozeilentool zu entwickeln.

Dir.open(".").each do |f|
  puts f if f =~ /\.rb/
end

puts

puts `ls *.rb`

Die beiden Programmteile sollen alle Rubyskripte im aktuellen Verzeichnis anzeigen, jedoch ist es durch die Verwendung von `ls *.rb` wesentlich leichter zu lesen, falls man sich bei der Bedienung einer POSIX-Shell auskennt. Im Zweifel sollten sie auf diese Methode nur zurückgreifen, falls sie explizit mit einem Programm arbeiten wollen und ansonsten sich auf reinen Rubycode beschränken. Das oben gezeigte Beispiel ist also schlechter Code, da er viele Voraussetzungen an andere Entwickler stellt - Sie müssen eine POSIX-Shell verwenden und mit dieser vertraut sein.

Eine bessere Verwendung zeigt sich in vielen Gemfiles von Entwicklern, die den Quellcode ihrer Gems mit Git verwalten. Gem und Gemfiles werden im Kapitel Rubygems näher erklärt, an dieser Stelle nur so viel: In einem Gemfile (Rubyquelltext) müssen alle Files stehen, die zu einem Gem gehören. Der Befehl git ls-files zeigt alle Dateien an, die aktuell mit Git verwaltet werden, dadurch ist es sehr einfach in Gemfiles durch die Zeile `git ls-files`.split("\n") alle verwalteten Dateien im Gemfile anzuzeigen.

Fehlerbehandlung

Bearbeiten

Die Kommandozeile erlaubt bestimmte Fähigkeiten im Umgang mit Fehlern eines Programmes, wenn es sich nach bestimmten Konventionen verhält. Das folgende Skript berechnet das Quadrat des Arguments und gibt es aus. Außerdem behandelt es den Fehler, das keine Zahl übergeben wurde:

number = ARGV[0]

if number.nil?
  $stderr.puts "This program expects a number to calculate it's square."
  exit 1
end

puts number.to_f ** 2

Falls Sie dieses Programmausführen sollten Sie keine Unterschiede zu bisherigen Skripten erkennen können unabhängig, ob Sie das Program korrekt oder Fehlerhaft benutzen. Die Unterschiede zeigen sich erst, wenn man die Kommandozeile benutzt, um das Programm in einen größeren Kontext einzubauen.

Es ist Möglich die Ausgabe eines Programmes umzulenken. Das kann dazu benutzt werden die Ausgaben zu ignorieren oder in einer Datei zu speichern. Es stehen dabei zwei unterschiedliche Ausgabewege zur Verfügung, die erste und der default, der mit puts angesprochen wird, heißt $stdout für das Anzeigen von Fehlern gibt es $stderr. Wenn Sie das Programm über die Kommandozeile mit ruby square.rb 2> /dev/null aufrufen, dann erhält unser Skript keine Argumente, da 2> /dev/null von der Kommandozeile verarbeitet wird, also entsteht der Fehler. Er wird aber nicht angezeigt, weil wir sagen, dass alle Meldungen im Zusammenhang mit Fehlern nach /dev/null schreiben, einen speziellen Ort auf Unixsystemen, der im wesentlichen wie ein Mülleimer funktioniert. Das Umleiten der Hauptausgabe erfolgt mit ruby square.rb 2 > result.

Daneben ist es manchmal nötig mehrere Programme zur Lösung eines Problems zu verwenden, wobei jedes Program einen Teil löst, aber nicht zwangsläufig funktioniert. Das nicht funktionieren eines Rubyskripts wird mit exit und einem Fehlercode, der nicht 0 sein darf, angezeigt. Dann wird bei folgendem Aufruf ruby square.rb && echo "Hello" das Wort Hello nicht ausgegeben, weil das zweite Program echo nur ausgeführt wird, wenn unser Skript funktioniert hätte.