Vorwort: Ich liebe Bash und habe nicht die Absicht, irgendwelche Auseinandersetzungen oder einen heiligen Krieg zu beginnen, und hoffentlich ist dies keine extrem naive Frage.
Diese Frage hat etwas mit diesem Beitrag zum Superuser zu tun, aber ich glaube nicht, dass der OP wirklich wusste, wonach er gefragt hat. Ich benutze Bash unter FreeBSD, Linux, OS X und Cygwin unter Windows. Ich habe in letzter Zeit auch umfangreiche Erfahrungen mit PowerShell unter Windows gesammelt.
Gibt es eine Shell für * nix, die bereits verfügbar ist oder in Arbeit ist, die mit bash kompatibel ist, der Mischung jedoch eine Ebene objektorientierten Skripts hinzufügt? Das einzige, von dem ich weiß, dass es nahe kommt, ist die Python-Konsole, aber soweit ich das beurteilen kann, bietet sie keinen Zugriff auf die Standard-Shell-Umgebung. Zum Beispiel kann ich nicht einfach cd ~
und ls
dann chmod +x file
in der Python-Konsole. Ich müsste Python verwenden, um diese Aufgaben anstatt der Standard-Unix-Binärdateien auszuführen, oder die Binärdateien mit Python-Code aufrufen.
Existiert eine solche Hülle?
quelle
cd ~
gefolgt vonls
Arbeiten wie in Bash. Sie können die Ausgabe auch Python-Variablen (Listen von Zeilen ...) mit Befehlen wie zuweisenlisting = !ls
.Antworten:
Ich kann mir drei wünschenswerte Funktionen in einer Shell vorstellen:
Unix-Shells konzentrieren sich in der Regel auf den interaktiven Aspekt und vergeben den größten Teil des Systemzugriffs und einen Teil der Programmierung an externe Tools, wie z.
ftp
für FTPmail
,Mail
,mailx
Etc. für grundlegende E-Mailcron
für geplante Aufgabendbus-*
oder qdbus ) für verschiedene Systeminformationen und Konfigurationsaufgaben (einschließlich moderner Desktop-Umgebungen wie KDE ≥4)Viele, viele Dinge können durch Aufrufen eines Befehls mit den richtigen Argumenten oder über eine Pipeline eingegeben werden. Dies ist ein sehr leistungsfähiger Ansatz - es ist besser, ein Tool pro Task zu haben, das dies gut macht, als ein einzelnes Programm, das alles andere als schlecht macht - aber es hat seine Grenzen.
Eine wesentliche Einschränkung von Unix-Shells, und ich vermute, das ist, was Sie mit Ihrer "objektorientierten Skripterstellung" fordern, dass sie nicht gut darin sind, Informationen von einem Befehl zum nächsten zu speichern oder Befehle in einer Weise zu kombinieren, die ausgefallener ist als eine Pipeline. Insbesondere die programmübergreifende Kommunikation basiert auf Text, sodass Anwendungen nur kombiniert werden können, wenn sie ihre Daten auf kompatible Weise serialisieren. Dies ist sowohl ein Segen als auch ein Fluch: Der Alles-ist-Text-Ansatz erleichtert das schnelle Ausführen einfacher Aufgaben, erhöht jedoch die Barriere für komplexere Aufgaben.
Interaktive Bedienbarkeit steht auch eher der Programmwartbarkeit entgegen. Interaktive Programme sollten kurz sein, wenig Anführungszeichen erfordern, Sie nicht mit Variablendeklarationen oder Eingaben belästigen usw. Wartungsfähige Programme sollten lesbar sein (also nicht viele Abkürzungen haben), sollten lesbar sein (damit Sie sich nicht wundern müssen, ob ein bloßes Wort vorkommt) Ist eine Zeichenfolge, ein Funktionsname, ein Variablenname usw.), sollten Konsistenzprüfungen wie Variablendeklarationen und Typisierung usw. durchgeführt werden.
Zusammenfassend ist eine Shell ein schwer zu erreichender Kompromiss. Ok, hiermit ist der Randalierungsabschnitt zu den Beispielen beendet.
Die Perl-Shell (psh) kombiniert die Interaktivität einer Unix-Shell mit der Leistungsfähigkeit von Perl. Einfache Befehle (auch Pipelines) können in der Shell-Syntax eingegeben werden. alles andere ist Perl. Das Projekt ist schon lange nicht mehr in der Entwicklung. Es ist verwendbar, hat aber noch nicht den Punkt erreicht, an dem ich erwägen würde, es über reines Perl (für Skripte) oder reine Shell (interaktiv oder für Skripte) zu verwenden.
IPython ist eine verbesserte interaktive Python-Konsole, die speziell für numerisches und paralleles Computing entwickelt wurde. Dies ist ein relativ junges Projekt.
irb (Interactive Ruby) ist das Ruby-Äquivalent der Python-Konsole.
scsh ist eine Schema-Implementierung (dh eine anständige Programmiersprache) mit der Art von Systembindungen, die traditionell in Unix-Shells (Strings, Prozesse, Dateien) zu finden sind. Es ist jedoch nicht das Ziel, als interaktive Shell verwendet zu werden.
zsh ist eine verbesserte interaktive Shell. Seine Stärke ist die Interaktivität (Kommandozeilen-Edition, Vervollständigung, allgemeine Aufgaben, die mit knapper, aber kryptischer Syntax ausgeführt werden). Die Programmierfunktionen sind nicht besonders gut (vergleichbar mit ksh), es gibt jedoch eine Reihe von Bibliotheken für die Terminalsteuerung, reguläre Ausdrücke, Netzwerke usw.
Fisch ist ein sauberer Start in eine Unix-Shell. Es gibt keine besseren Programmier- oder Systemzugriffsfunktionen. Weil es die Kompatibilität mit sh bricht, hat es mehr Raum, um bessere Funktionen zu entwickeln, aber das ist nicht geschehen.
Nachtrag: Ein weiterer Teil der Unix-Toolbox behandelt viele Dinge als Dateien:
/sys
Bietet unter Linux mehr Hardware- und Systemsteuerung./proc
Dateisystem erfolgen.Vielleicht ist die Zukunft von Unix-Shells nicht ein besserer Systemzugriff über Befehle (und bessere Kontrollstrukturen zum Kombinieren von Befehlen), sondern ein besserer Systemzugriff über Dateisysteme (die sich etwas anders kombinieren - ich glaube nicht, dass wir herausgefunden haben, wie die wichtigsten Redewendungen lauten (wie) das Mantelrohr) sind noch).
quelle
Sie benötigen nicht viel Bash-Code, um Klassen oder Objekte in Bash zu implementieren.
Sagen wir 100 Zeilen.
Bash verfügt über assoziative Arrays, mit denen ein einfaches Objektsystem mit Vererbung, Methoden und Eigenschaften implementiert werden kann.
Sie könnten also eine Klasse wie diese definieren:
Das Erstellen einer Instanz dieser Warteschlange kann folgendermaßen erfolgen:
oder
Da Klassen mit einem Array implementiert werden, sind class und inst wirklich Synonyme - ähnlich wie in Javascript.
Das Hinzufügen von Elementen zu dieser Warteschlange könnte folgendermaßen erfolgen:
Das Entfernen von Elementen in eine Variable X kann folgendermaßen erfolgen:
Die Dump-Struktur eines Objekts könnte folgendermaßen aussehen:
Welches würde so etwas zurückgeben:
Klassen werden mit einer Klassenfunktion wie der folgenden erstellt:
ANMERKUNG: Wenn Sie eine neue Klasse oder Instanz definieren, können Sie jeden Mitgliedswert oder jede Funktion überschreiben.
Assoziative Bash-Arrays haben eine Besonderheit, die diese Funktion sehr übersichtlich macht: $ Q [0]} ist identisch mit $ Q. Dies bedeutet, dass wir den Array-Namen verwenden können, um eine Methode-Dispatch-Funktion aufzurufen:
Ein Nachteil ist, dass ich [0] nicht für Daten verwenden kann, sodass meine Warteschlangen (in diesem Fall) bei index = 1 beginnen. Alternativ hätte ich assoziative Indizes wie "q + 0" verwenden können.
Um Mitglieder zu bekommen und zu setzen , könnten Sie Folgendes tun:
Und Dump eine Objektstruktur, habe ich dies:
HINWEIS: Dies ist für OOP in bash nicht erforderlich, aber es ist schön zu sehen, wie Objekte erstellt werden.
In meinem OOP-Design wurden keine Objekte innerhalb von Objekten berücksichtigt - mit Ausnahme der geerbten Klasse. Sie können sie separat erstellen oder einen speziellen Konstruktor wie class () erstellen. * obj_dump * müsste geändert werden, um interne Klassen zu erkennen und diese rekursiv zu drucken.
Oh! und ich definiere manuell eine ROOT-Klasse, um die Klassenfunktion zu vereinfachen :
Mit ein paar Queue-Funktionen habe ich einige Klassen wie folgt definiert:
Einige Warteschlangeninstanzen erstellt und funktionsfähig gemacht:
quelle
bash
. Erinnert mich an Stephanes Antwort, warum man keine Shell-Schleifen zum Verarbeiten von Text verwendet, insbesondere den Abschnitt "Konzeptuell", in dem der Zweckunterschied zwischen Sprachen wie C undbash
. unix.stackexchange.com/a/169765/135943ksh93t + führt einige OO-Konzepte unter Beibehaltung der bourne / posix-Shell-Syntax ein: http://blog.fpmurphy.com/2010/05/ksh93-using-types-to-create-object-orientated-scripts.html
quelle
IPython ist überraschend bequem zu bedienen.
Standard-Shell-Funktionen: Jobsteuerung, Readline-Bearbeitung und -Verlauf, Aliase
cat
ls
cd
undpwd
Pager-Integration, Ausführen eines Systembefehls durch Präfixieren!
oder Aktivieren einer%rehashx
Befehlsausgabe, die einer Python-Variablen zugewiesen werden kann, Python-Werte, die als Shell-Variablen verfügbar sind.Python-spezifisch: Wiederverwendung der Ergebnisse der letzten Befehle, schneller Zugriff auf Dokumentation und Quelle, erneutes Laden von Modulen, Debugger. Einige Cluster-Unterstützung, wenn Sie in das sind.
Das heißt, das Ausführen komplexer Pipes wird in Python nicht ausgeführt. Sie werden auch die Posix-Shell verwenden, nur mit etwas Kleber, um Werte hin und her zu übertragen.
quelle
Es gibt Rush, der Ruby verwendet, und Psh, das auf Perl basiert.
quelle
jq
funktioniert ganz gut als so eine art objektorientierte schicht.quelle
Dieser ist etwas einfacher zu bedienen und einzurichten, hat den Namen args usw. https://github.com/uudruid74/bashTheObjects
Ich aktualisiere meine Antwort mit einem Beispiel, das einem der grundlegenden Beispiele für eine andere Antwort folgt, aber mit dieser Syntax. Das Beispielprogramm ist ähnlich, aber Sie müssen nicht allen Variablen den Klassennamen voranstellen (dies ist bekannt, wie die kindof- Methode zeigt), und ich denke, die Syntax ist viel einfacher!
Zuerst eine Klassendatei. Die Standardwerte für die Instanzvariablen sind optional und werden nur verwendet, wenn Sie diese Werte nicht an den Konstruktor übergeben.
Nun zum Beispiel Verwendung:
ANMERKUNGEN:
Die import-Anweisung ist technisch nicht erforderlich, erzwingt jedoch das Laden der Klasse zum angegebenen Zeitpunkt, anstatt auf die erste neue zu warten. Dies kann dazu beitragen, die Dinge in der richtigen Reihenfolge zu initialisieren. Beachten Sie, wie einfach es ist, mehrere Instanzvariablen gleichzeitig festzulegen.
Es gibt auch Debug-Ebenen, Konstruktoren, Destruktoren, Unterklassen und ein grundlegendes Reflektionssystem , und es wird print / println angezeigt , um das Echo zu ersetzen (versuchen Sie jemals, eine Variable zu drucken, die mit einem Bindestrich beginnt?). Das Beispiel auf github zeigt, wie es als CGI ausgeführt wird, das HTML aus Klassen generiert.
Die Bibliothek selbst (oop.lib.sh) ist nicht so einfach (mehr als 400 Zeilen, 11 KB), aber Sie schließen sie einfach ein und vergessen sie.
quelle
Sie können PowerShell Core Edition jetzt unter Linux installieren . Es läuft auf dem plattformübergreifenden .NET Core Framework, das derzeit von Microsoft entwickelt wird.
quelle
Wenn jemand nur die Grundlagen der objektorientierten Programmierung (Eigenschaften und Methoden) möchte, reicht ein wirklich einfaches Framework aus.
Angenommen, Sie möchten den Text "Hello World" mithilfe von Objekten anzeigen. Zuerst erstellen Sie eine Objektklasse, die eine Eigenschaft für den anzuzeigenden Text und einige Methoden zum Festlegen und Anzeigen dieses Texts enthält. Um zu zeigen, wie mehrere Instanzen einer Klasse zusammenarbeiten können, habe ich zwei Methoden zum Anzeigen des Texts hinzugefügt: eine mit NewLine am Ende und eine ohne NewLine.
Klassendefinitionsdatei : EchoClass.class
Bitte beachten Sie das Wort "<<Instanzname>>". Dies wird später ersetzt, um mehrere Instanzen eines Klassenobjekts zu erstellen. Bevor Sie eine Instanz eines Objekts verwenden können, benötigen Sie eine Funktion, die es tatsächlich erstellt. Zur Vereinfachung wird es ein separates Skript mit dem Namen ObjectFramework.lib geben
Jetzt haben wir eine Klassendefinitionsdatei und eine CreateObject-Funktion, die eine Kopie dieser Datei erstellt, wobei der Text "<<InstanceName>>" durch einen beliebigen Namen ersetzt wird.
Lassen Sie uns unser neues Objekt in einem Skript namens HelloWorld.sh verwenden (bitte beachten Sie, dass HelloWorld.sh ausführbar sein sollte. Die anderen beiden Dateien müssen nicht).
Durch Ausführen des Skripts HelloWorld.sh wird der Text "Hello World" angezeigt (und eine neue Zeile hinzugefügt). Niemand wird von diesem Ergebnis beeindruckt sein, aber wir werden wissen, dass dies nicht so einfach ist, wie es aussieht :)
Viel Spaß beim Codieren!
quelle
Dies ist eine objektorientierte Shell, die auf Python basiert, aber eine ähnliche Sintaxe wie Golang hat: https://github.com/alexst07/shell-plus-plus
Versuchen Sie zum Beispiel, catch:
Klassen- und Operatorüberladung:
und Sie können die Befehle ähnlich Bash verwenden:
quelle
Mit welchen Objekten beschäftigen Sie sich die meiste Zeit in einer Shell? Es sind Dateien / Verzeichnisse, Prozesse und deren Interaktion. So sollte es gefallen
f1.edit
oder so ähnlichcurrentFile=f1.c ; .edit ; .compile ; .run
. Oderd1.search(filename='*.c' string='int \*')
. Oderp1.stop
,p1.bg
. So verstehe ich eine Muschel.quelle
Ich habe gerade versucht, oo-Konzepte basierend auf der Referenz http://hipersayanx.blogspot.in/2012/12/object-oriented-programming-in-bash.html in bash einzuführen
quelle
Sorry für die kurze Antwort aber hier geht es weiter.
hipersayanx hat einen Artikel Objektorientierte Programmierung in Bash erstellt . Grundsätzlich er hallo-aufgebockt
$FUNCNAME
,function
,compgen
, undexport
so nah zu schaffen , um OOP ein in bash zu bekommen.Das coole daran ist, dass es gut funktioniert und man nur ein paar Zeilen Boilerplating braucht, um eine Klasse aufzubauen.
Grundlegende Teile benötigt werden:
Verwendung:
Jetzt habe ich dies selbst in meinem AuditOps-Projekt verwendet und hipersayanx hat weitere Details darüber, wie dies auf seiner Website tatsächlich funktioniert. Tarifwarnungen, obwohl dies sehr bashistisch ist, funktionieren nicht mit älteren Versionen als Bash 4.0 und können zu Kopfschmerzen beim Debuggen führen. Während ich persönlich möchte, dass die meisten Kesselbeschichtungen als Klasse selbst erneuert werden.
Es ist immer klüger, eine seriöse OOP-Skriptsprache wie Perl, Ruby und Python zu verwenden, wenn dies für Ihr Projekt besser geeignet ist. Meiner Meinung nach ist es jedoch die Zeit und Mühe wert, wenn modulare Bash-Skripte verwaltet werden, um diese OOP-Methode in Bash zu verwenden.
quelle
Ich entwickle auf GitHub eine Funktion, die genauso funktioniert wie ein HashMap-Objekt , shell_map .
Um " HashMap-Instanzen " zu erstellen, kann diese Funktion Kopien von sich selbst unter verschiedenen Namen erstellen. Jede neue Funktionskopie hat eine andere Variable $ FUNCNAME. Mit $ FUNCNAME wird dann für jede Map-Instanz ein Namespace erstellt.
Die Map-Schlüssel sind globale Variablen im Format $ FUNCNAME_DATA_ $ KEY, wobei $ KEY der der Map hinzugefügte Schlüssel ist. Diese Variablen sind dynamische Variablen .
Unten werde ich eine vereinfachte Version davon einfügen, damit Sie sie als Beispiel verwenden können.
Verwendung:
quelle
carp "Some error message"; return
stattdessen zu verwenden .[ -z "$KEY" ] && { carp "some message"; return;}
Keine Notwendigkeit für eine Unterschale. Aber tatsächlich sieht das wie ein tatsächlicher Kandidat für einif ... elif ... elif ... else ... fi
Konstrukt aus - was hier nicht oft die beste Wahl ist, aber wahrscheinlich ist. :) (Oder vielleicht ein Fall wechseln.)Plumbum ist eine Python-ähnliche Shell-Sprache. Es enthält eine Shell-ähnliche Syntax mit Python, die die Erfahrung objektorientiert macht.
quelle