BEARBEITEN: Bitte, bitte , bitte lesen Sie die beiden Anforderungen, die am Ende dieses Beitrags aufgeführt sind, bevor Sie antworten. Die Leute veröffentlichen immer wieder ihre neuen Juwelen und Bibliotheken und so weiter, die eindeutig nicht den Anforderungen entsprechen.
Manchmal möchte ich einige Befehlszeilenoptionen sehr billig in ein einfaches Skript hacken. Eine unterhaltsame Möglichkeit, dies zu tun, ohne sich mit Getopts, Parsing oder Ähnlichem zu befassen, ist:
...
$quiet = ARGV.delete('-d')
$interactive = ARGV.delete('-i')
...
# Deal with ARGV as usual here, maybe using ARGF or whatever.
Es ist nicht ganz die normale Unix-Optionssyntax, da sie Optionen akzeptiert, die keine Optionsbefehlszeilenparameter sind, wie in " myprog -i foo bar -q
", aber damit kann ich leben. (Einige Leute, wie die Subversion-Entwickler, bevorzugen dies. Manchmal auch.)
Eine Option, die nur vorhanden ist oder fehlt, kann nicht viel einfacher als die oben genannte implementiert werden. (Eine Zuweisung, ein Funktionsaufruf, ein Nebeneffekt.) Gibt es eine ebenso einfache Möglichkeit, mit Optionen umzugehen, die einen Parameter annehmen, z. B. " -f
Dateiname "?
BEARBEITEN:
Ein Punkt, den ich vorher nicht angesprochen habe, weil mir erst klar geworden war, als der Autor von Trollop erwähnte, dass die Bibliothek "in eine [800-Zeilen] -Datei" passt, ist, dass ich nicht nur nach sauber suche Syntax, jedoch für eine Technik mit folgenden Eigenschaften:
Der gesamte Code kann in die Skriptdatei aufgenommen werden (ohne das eigentliche Skript selbst zu überfordern, das nur ein paar Dutzend Zeilen umfassen kann), sodass eine einzelne Datei in einem
bin
Verzeichnis auf jedem System mit einem Standard-Ruby 1.8 abgelegt werden kann [5-7] installieren und verwenden. Wenn Sie kein Ruby-Skript schreiben können, für das keine erforderlichen Anweisungen erforderlich sind und der Code zum Parsen einiger Optionen weniger als ein Dutzend Zeilen enthält, besteht diese Anforderung nicht.Der Code ist klein und einfach genug, dass man sich genug daran erinnern kann, um direkt Code einzugeben, der den Trick macht, anstatt ihn von einem anderen Ort aus auszuschneiden und einzufügen. Stellen Sie sich die Situation vor, in der Sie sich auf der Konsole eines Firewall-Servers ohne Internetzugang befinden und ein schnelles Skript für einen Client zusammenstellen möchten. Ich weiß nichts über dich, aber (abgesehen davon, dass ich die oben genannten Anforderungen nicht erfüllt habe) ist es mir nicht wichtig, mir selbst die 45 Zeilen vereinfachter Mikrooptik zu merken.
getoptlong
undoptparse
befinden sich in der Standard-Ruby-Bibliothek, sodass Sie sie bei der Bereitstellung Ihres Skripts nicht kopieren MÜSSEN - wenn Ruby auf diesem Computer funktioniert, dannrequire 'optparse'
oderrequire 'getoptlong'
auch.Antworten:
Als Autor von Trollop kann ich nicht glauben , was die Leute in einem Optionsparser für vernünftig halten. Ernsthaft. Es verwirrt den Geist.
Warum sollte ich ein Modul erstellen müssen, das ein anderes Modul erweitert, um Optionen zu analysieren? Warum sollte ich etwas unterordnen müssen? Warum sollte ich ein "Framework" abonnieren müssen, um die Befehlszeile zu analysieren?
Hier ist die Trollop-Version von oben:
Und das ist es.
opts
ist nun ein Hash mit Tasten:quiet
,:interactive
, und:filename
. Sie können damit machen, was Sie wollen. Und Sie erhalten eine schöne Hilfeseite, die an Ihre Bildschirmbreite angepasst ist, automatische Kurzargumentnamen, Typprüfung ... alles, was Sie brauchen.Es ist eine Datei, sodass Sie sie in Ihrem lib / -Verzeichnis ablegen können, wenn Sie keine formale Abhängigkeit wünschen. Es hat ein minimales DSL, das leicht zu erlernen ist.
LOC pro Option Personen. Es ist wichtig.
quelle
Ich teile Ihre Abneigung gegen
require 'getopts'
, vor allem wegen der Großartigkeit, die istOptionParser
:quelle
Hier ist die Standardtechnik, die ich normalerweise verwende:
quelle
lib
Ihrem Ordner oder Code ablegen und verwenden, ohne Rubygems zu berühren.when /^-/ then usage("Unknown option: #{ARGV[0].inspect}")
zuwhen /^-/ then usage("Unknown option: #{ARGV.shift.inspect}")
oder es würde in eine unendliche Nutzungs Schleife bekommenDa schien es niemand zu erwähnen, und der Titel bezieht sich billig Befehlszeilen Parsing, warum nicht nur die Ruby - Interpreter lassen die Arbeit für Sie tun? Wenn Sie den
-s
Schalter übergeben (zum Beispiel in Ihrem Shebang), erhalten Sie kostenlos schmutzige Schalter, die globalen Variablen mit einem Buchstaben zugewiesen sind. Hier ist Ihr Beispiel mit diesem Schalter:Und hier ist die Ausgabe, wenn ich das speichere als
./test
und chmod+x
:Siehe
ruby -h
für Details.Das muss so billig sein wie es nur geht. Es wird ein NameError ausgelöst, wenn Sie einen Schalter wie versuchen
-:
, also gibt es dort eine Validierung. Natürlich können Sie nach einem Nicht-Schalter-Argument keine Schalter haben, aber wenn Sie etwas Besonderes benötigen, sollten Sie wirklich mindestens den OptionParser verwenden. Das einzige, was mich an dieser Technik ärgert, ist, dass Sie beim Zugriff auf eine nicht gesetzte globale Variable eine Warnung erhalten (wenn Sie sie aktiviert haben), aber sie ist immer noch falsch, sodass sie für Wegwerfwerkzeuge gut und schnell funktioniert Skripte.Eine Einschränkung, auf die FelipeC in den Kommentaren in " Wie man wirklich billige Befehlszeilenoptionen in Ruby analysiert " hinweist , ist, dass Ihre Shell den 3-Token-Shebang möglicherweise nicht unterstützt. Möglicherweise müssen Sie
/usr/bin/env ruby -w
den tatsächlichen Pfad zu Ihrem Ruby (wie/usr/local/bin/ruby -w
) ersetzen oder ihn über ein Wrapper-Skript oder etwas anderes ausführen.quelle
Ich habe Micro-Optparse entwickelt , um diesen offensichtlichen Bedarf an einem kurzen, aber einfach zu verwendenden Options-Parser zu decken . Es hat eine ähnliche Syntax wie Trollop und ist 70 Zeilen kurz. Wenn Sie keine Validierungen benötigen und auf leere Zeilen verzichten können, können Sie diese auf 45 Zeilen reduzieren. Ich denke, genau das haben Sie gesucht.
Kurzes Beispiel:
Aufruf des Skripts mit
-h
oder--help
wird gedrucktEs prüft, ob die Eingabe vom gleichen Typ wie der Standardwert ist, generiert kurze und lange Accessoren, druckt beschreibende Fehlermeldungen, wenn ungültige Argumente angegeben werden, und vieles mehr.
Ich habe mehrere Optionsparser verglichen, indem ich jeden Optionsparser für das Problem verwendet habe, das ich hatte. Sie können diese Beispiele und meine Zusammenfassung verwenden, um eine informative Entscheidung zu treffen. Fühlen Sie sich frei, der Implementierung weitere Implementierungen hinzuzufügen. :) :)
quelle
optparse
1937 Zeilen abhängen und diese benötigen (geben oder nehmen).optparse
es sich um eine Standardbibliothek handelt, dh sie wird mit jeder Ruby-Installation geliefert.Trollop
ist eine Bibliothek eines Drittanbieters, daher müssen Sie den vollständigen Code jedes Mal importieren, wenn Sie ihn in ein Projekt aufnehmen möchten. µ-optparse benötigt immer nur die ~ 70 Zeilen, da dieseoptparse
bereits vorhanden sind.Ich verstehe vollkommen, warum Sie Optparse vermeiden wollen - es kann zu viel werden. Es gibt jedoch einige weitaus "leichtere" Lösungen (im Vergleich zu OptParse), die als Bibliotheken geliefert werden, aber einfach genug sind, um eine einzelne Edelsteininstallation lohnenswert zu machen.
Zum Beispiel Besuche dieses OptiFlag Beispiel . Nur ein paar Zeilen für die Bearbeitung. Ein leicht verkürztes Beispiel, das auf Ihren Fall zugeschnitten ist:
Es gibt auch Tonnen von kundenspezifischen Beispielen . Ich erinnere mich, dass ich ein anderes verwendet habe, das noch einfacher war, aber es ist mir vorerst entgangen, aber ich werde zurückkommen und hier einen Kommentar hinzufügen, wenn ich ihn finde.
quelle
Dies ist, was ich für wirklich, wirklich billige Argumente benutze:
Wenn Sie also ausführen
programname foo bar
, wird foo und dann bar aufgerufen. Es ist praktisch für Wegwerfskripte.quelle
Sie können etwas versuchen wie:
quelle
Haben Sie Thor von Wycats in Betracht gezogen? Ich denke, es ist viel sauberer als optparse. Wenn Sie bereits ein Skript geschrieben haben, ist es möglicherweise etwas aufwendiger, es zu formatieren oder für thor umzugestalten, aber es macht die Handhabungsoptionen sehr einfach.
Hier ist das Beispiel-Snippet aus der README:
Thor ordnet Befehle automatisch als solche zu:
Das wird konvertiert zu:
quelle
--help
Ausgabe drucken müssen ? Was ist, wenn "head myprogram.rb" die Hilfeausgabe war?Hier ist mein Lieblings-Parser für schnelle und schmutzige Optionen:
Die Optionen sind reguläre Ausdrücke, daher würde "-h" auch mit "--help" übereinstimmen.
Lesbar, leicht zu merken, keine externe Bibliothek und minimaler Code.
quelle
/-h(\b|elp)
Trollop ist ziemlich billig.
quelle
Wenn Sie einen einfachen Befehlszeilenparser für Schlüssel- / Wertbefehle ohne Verwendung von Edelsteinen benötigen:
Aber dieses funktioniert jedoch nur, wenn Sie immer Schlüssel / Wert-Paare haben.
Wenn Sie keine Überprüfung benötigen, können Sie einfach Folgendes verwenden:
quelle
Hier ist das Code-Snippet, das ich oben in den meisten meiner Skripte verwende:
Ich hasse es auch, zusätzliche Dateien in meinen schnellen und schmutzigen Skripten zu benötigen. Meine Lösung ist fast das, wonach Sie fragen. Ich füge einen 10-zeiligen Codeausschnitt oben in eines meiner Skripte ein, der die Befehlszeile analysiert, Positionsargumente speichert und in ein Hash-Objekt wechselt (normalerweise einem Objekt zugewiesen, das ich arghash genannt habe in den folgenden Beispielen ).
Hier ist ein Beispiel für eine Befehlszeile, die Sie möglicherweise analysieren möchten ...
Welches würde ein Hash wie dieser werden.
Darüber hinaus werden dem Hash zwei praktische Methoden hinzugefügt:
argc()
gibt die Anzahl der Nicht-Switch-Argumente zurück.switches()
gibt ein Array zurück, das die Schlüssel für vorhandene Schalter enthältDies soll ein paar schnelle und schmutzige Sachen wie ...
arghash.argc == 2
) übergebenenarghash[1]
immer das zweite Nicht-Schalter-Argument abgerufen).arghash['--max=']
wodurch in der Beispielbefehlszeile der Wert '15' erhalten wird.arghash['-s']
wahr ausgewertet wird, wenn sie vorhanden ist, und als Null, wenn sie nicht vorhanden ist.Testen Sie das Vorhandensein eines Schalters oder von Alternativen von Schaltern mit festgelegten Operationen wie
puts USAGETEXT if !(%w(-h --help) & arghash.switches()).empty?
Identifizieren Sie die Verwendung ungültiger Schalter mithilfe von Set-Operationen wie z
puts "Invalid switch found!" if !(arghash.switches - %w(-valid1 -valid2)).empty?
Geben Sie Standardwerte für fehlende Argumente an, indem Sie ein einfaches Beispiel
Hash.merge()
wie das folgende verwenden, das einen Wert für -max = ausfüllt, wenn eines nicht festgelegt wurde, und ein viertes Positionsargument hinzufügt, wenn eines nicht übergeben wurde.with_defaults = {'-max=' => 20, 3 => 'default.txt'}.merge(arghash)
quelle
=
) einen Unterschied im benötigten Code bewirken kann.Dies ist der akzeptierten Antwort sehr ähnlich, aber mit
ARGV.delete_if
welcher ich sie in meinem einfachen Parser . Der einzige wirkliche Unterschied besteht darin, dass Optionen mit Argumenten zusammen sein müssen (z-l=file
. B. ).quelle
Anscheinend denken @WilliamMorgan und ich gleich. Ich habe gestern Abend für Github veröffentlicht. Was ich jetzt sehe, ist eine ähnliche Bibliothek wie Trollop (benannt wie?), Nachdem ich auf Github nach OptionParser gesucht habe, siehe Switches
Es gibt einige Unterschiede, aber die Philosophie ist dieselbe. Ein offensichtlicher Unterschied besteht darin, dass Switches von OptionParser abhängig sind.
quelle
Ich entwickle mein eigenes Optionsparser-Juwel namens Acclaim .
Ich habe es geschrieben, weil ich Befehlszeilenschnittstellen im Git-Stil erstellen und die Funktionalität jedes Befehls sauber in separate Klassen unterteilen wollte, aber es kann auch ohne das gesamte Befehlsframework verwendet werden:
Noch keine stabile Version, aber ich habe bereits einige Funktionen implementiert wie:
Es wird viel Wert auf Befehle gelegt, daher ist es für das einfache Parsen von Befehlszeilen möglicherweise etwas schwer, aber es funktioniert gut und ich habe es in all meinen Projekten verwendet. Wenn Sie sich für den Aspekt der Befehlsoberfläche interessieren, finden Sie auf der GitHub-Seite des Projekts weitere Informationen und Beispiele.
quelle
Angenommen, ein Befehl hat höchstens eine Aktion und eine beliebige Anzahl solcher Optionen:
Das Parsen ohne Validierung kann folgendermaßen aussehen:
quelle
https://github.com/soveran/clap
46LOC (bei 1.0.0), keine Abhängigkeit vom externen Optionsparser. Erledigt die Arbeit. Wahrscheinlich nicht so voll ausgestattet wie andere, aber es ist 46LOC.
Wenn Sie den Code überprüfen, können Sie die zugrunde liegende Technik ziemlich einfach duplizieren - weisen Sie Lambdas zu und verwenden Sie die Arität, um sicherzustellen, dass die richtige Anzahl von Argumenten dem Flag folgt, wenn Sie wirklich keine externe Bibliothek möchten.
Einfach. Billig.
BEARBEITEN : Das zugrunde liegende Konzept ist auf den Punkt gebracht, da Sie es möglicherweise kopieren / in ein Skript einfügen, um einen vernünftigen Befehlszeilenparser zu erstellen. Es ist definitiv nichts, was ich in Erinnerung behalten würde, aber die Lambda-Arität als billigen Parser zu verwenden, ist eine neuartige Idee:
quelle
Ich werde meinen eigenen einfachen Optionsparser teilen, an dem ich seit einiger Zeit arbeite. Es sind lediglich 74 Codezeilen und es werden die Grundlagen des internen Optionsparsers des Git erläutert. Ich habe OptionParser als Inspiration genommen und auch Git's.
https://gist.github.com/felipec/6772110
Es sieht aus wie das:
quelle
EasyOptions erfordert überhaupt keinen Optionsparsing-Code. Schreiben Sie einfach den Hilfetext, benötigen Sie, fertig.
quelle