Herausforderung : Schreiben Sie eine einzelne Skriptdatei, foo.cmd
die über die Vanilla Windows- cmd.exe
Eingabeaufforderung aufgerufen werden kann (nicht PowerShell, nicht im Administratormodus), um beliebigen Windows-spezifischen Code auszuführen ...
> .\foo.cmd
Hello Windows!
... aber auch aus einem typischen POSIX-konform (Linux / OSX) Shell - Eingabeaufforderung (unverändert aufgerufen werden bash
, tcsh
oder zsh
), willkürlichen POSIX-spezifischen Code auszuführen:
$ chmod a+x foo.cmd
$ ./foo.cmd
Hello POSIX!
... ohne Installation oder Erstellung von Dolmetschern / Tools von Drittanbietern.
Ich weiß, dass dies möglich ist, aber mit cruft (dh unter Windows werden ein oder zwei Zeilen Müll / Fehlermeldung vor "Hallo Windows!" Nach stderr oder stdout gedruckt).
Das Gewinnkriterium ist die Minimierung von (erstens) der Anzahl der Cruft-Linien und (zweitens) der Anzahl der Cruft-Zeichen.
Cruft kann als eine beliebige Konsolenausgabe (stdout oder stderr) definiert werden, die nicht vom (beliebigen) Nutzlastcode erzeugt wird. Leerzeilen werden in der Zeilenanzahl gezählt. Zeilenumbrüche werden bei der Zeichenanzahl nicht berücksichtigt. Cruft-Scores sollten auf beiden Plattformen summiert werden. Lassen Sie uns cls
solche Mechanismen außer Acht , die die Cruft wegfegen, aber auf Kosten der Ausblendung der vorherigen Terminal-Ausgabe. Wenn Windows Ihre Befehle wiederholt, weil Sie noch nicht gedreht @echo off
haben, schließen wir die Zeichen aus, die beim Drucken des aktuellen Verzeichnisses und der Eingabeaufforderung verwendet werden.
Ein sekundäres Kriterium ist die Einfachheit / Eleganz der darin enthaltenen Lösung foo.cmd
: Wenn "Infrastruktur" als ein Zeichen definiert ist, das nicht direkt in den beliebigen Nutzlastcode einbezogen ist, minimieren Sie zuerst die Anzahl der Zeilen, die Infrastrukturzeichen enthalten, und zweitens die Gesamtzahl der Infrastrukturen Zeichen.
Ein großes Lob, wenn der POSIX-Teil trotz der Datei mit CRLF-Zeilenenden funktioniert! (Bin mir nicht sicher, ob der letzte Teil überhaupt möglich ist.)
Meine vorhandene Lösung, die ich hier veröffentlichen werde, sobald andere eine Chance hatten, verwendet 6 Zeilen Infrastrukturcode (52 Zeichen ohne Zeilenumbrüche). Es werden 5 Cruft-Zeilen erzeugt, von denen zwei leer sind und alle unter Windows vorkommen (30 Zeichen ohne Zeilenumbrüche und ohne die aktuelle Verzeichnis- / Eingabeaufforderungszeichenfolge, die in zwei dieser Zeilen angezeigt wird).
Antworten:
0 cruft lines, 0 cruft chars, 2 infra. Linien, 21 infra. Zeichen, CRLF ok
Die andere Lösung wurde entfernt.
17 Zeichen
exit /b
aus der Antwort von Digital Trauma:quelle
: command not found
wenn sich eine leere Zeile in die Nutzlast von posix eingeschlichen hatte, aber schließlich stellte ich fest, dass dies nicht:
in der ersten Zeile, sondern aufgrund von ungeschützten CRLFs der Fall war#
. Es war eine Neuigkeit für mich, dass eine#!
Leitung nicht benötigt wird - das war für zwei der Leitungen von Windows Cruft in meiner vorherigen Version verantwortlich.: ` >&3` \
zu jeder Zeile der Nutzlast hinzufügt , kann man davon ausgehen, dass die Infrastrukturkosten beliebig hoch sind.#
nötig?Punktzahl 0 cruft + 4 infra lines + 32 infra chars. LF & CRLF OK.
Dies basiert auf dem, was ich in diesem Blog gefunden habe , wobei die Amiga-Bits und andere unnötige Zeilen entfernt wurden. Ich habe die DOS-Zeilen in kommentierten Anführungszeichen ausgeblendet, anstatt
\
line continue zu verwenden, damit dies sowohl mit CRLF als auch mit LF funktioniert.Mit den Zeilenenden DOS CRLF oder * nix LF funktioniert es unter Ubuntu, OSX und Wine:
Um dies genau (mit CRLFs) auf einem * nix-Computer (einschließlich OSX) zu erstellen, fügen Sie Folgendes in ein Terminal ein:
quelle
dosix
ist auch ein schöner Name. Aber auf meinem Mac (OS 10.9.4, Darwin Kernel Version 13.3.0, GNU bash Version 3.2.51) funktioniert es nicht mit: Keine./dosix.cmd: line 13: syntax error: unexpected end of file
Ahnung warum?Ich werde die Lösung, die ich verwendet habe, bereits posten, da sie bereits geschlagen wurde. Es ist mit freundlicher Genehmigung eines Kollegen von mir, von dem ich denke, dass er denselben Blogeintrag wie Digital Trauma gelesen hat .
#!
Zeile angegebene Dolmetscher sich nicht darum kümmert (für Standarddolmetscher wiesh
und Freunde schlägt dies fehl)quelle
#!
, was bedeutet, dass Sie die einzige Antwort sind, die auf einem POSIX-System gültig ist. Sicher, einige der anderen können ausgeführt werden, wenn - aber nur, wenn sie von einer Shell mit einer Problemumgehung für fehlerhafte Skripte gestartet werden.#!
Zeile, aber sie verwenden unterschiedliche Shells für die Interpretation des Skripts. Das bedeutet, dass ein "Skript", das nicht mit "" beginnt,#!
nicht nur in einer Shell gültig sein muss, sondern in jeder Shell, von der es plausibel interpretiert werden könnte. Schlimmer noch, es funktioniert nur, wenn es von einer anderen Shell gestartet wird. Ein solches Skript funktioniert möglicherweise über die Befehlszeile, jedoch nicht in dem Kontext, in dem Sie es endgültig verwenden möchten.#!
Zeile in meiner bearbeiteten Antwort (1 Infrastrukturzeile mit 21 Zeichen) mit der Antwort einer anderen Person zu einem Windows-Cruft-Preis von 2 Zeilen (von denen eine leer ist) oder kombiniert werden 23 Zeichen.Zusammenfassung / Synthese der Antworten und Diskussion
Das hat Spaß gemacht und ich habe viel gelernt.
Einige Windows-spezifische Probleme sind unvermeidlich, wenn Sie auf Ihrem POSIX-System Ihr Skript mit einer
#!
Zeile beginnen müssen. Wenn Sie keine andere Wahl haben, als dies zu tun, dann ist diese Zeile:ist wahrscheinlich das Beste, was es bekommen kann. Auf der Windows-Konsole werden eine Leerzeile und eine Cruft-Zeile ausgegeben. Aber Sie können der Lage sein , ohne wegzukommen
#!
Linie: auf den meisten Systemen, eine der üblichen Shell - Interpreter wird die Ausführung des Skripts am Ende (das Problem ist , dass es nicht allgemein vorhersehbar ist , welche Interpreter das sein wird - es hängt davon ab, wird aber nicht unbedingt identisch sein mit der Shell, mit der Sie den Befehl aufrufen).Jenseits dieser kniffligen ersten Zeile gab es einige wirklich geniale Lösungen, die nichts mit Krüppeln zu tun hatten. Der Gewinnerbeitrag von jimmy23013 bestand nur aus zwei kurzen Infrastrukturlinien und nutzte die doppelte Rolle des
:
Charakters, um auf beiden Plattformen eine "stille" Linie zu implementieren (als De-facto- No-Op-Insh
und Freunde sowie als Label) Markierung incmd.exe
):Es ist möglich, ein solches Skript trotz CRLF-Zeilenenden auf POSIX-Systemen auszuführen. Für die meisten Interpreter müssen Sie jedoch jede Zeile Ihres POSIX-Abschnitts (auch leere Zeilen) mit einem Kommentar oder Kommentarzeichen beenden .
Schließlich sind hier zwei Varianten einer Lösung, die ich auf der Grundlage der Beiträge aller entwickelt habe. Sie könnten fast das Beste aus beiden Welten, indem sie den Schaden aus dem Mangel an minimieren
#!
und CRLF-Kompatibilität machen noch glatter. Es werden zwei zusätzliche Infrastrukturleitungen benötigt. Nur eine (standardisierte) Zeile muss von der unvorhersehbaren POSIX-Shell interpretiert werden. In dieser Zeile können Sie die Shell für den Rest des Skripts auswählen (bash
im folgenden Beispiel):Das Schöne an diesen heredoc-Lösungen ist, dass sie immer noch CRLF-robust sind: Solange
<<:Z
das Ende der Reihe erreicht ist, sucht und findet der heredoc-Prozessor das Token:Z\r
Als letzte Wendung können Sie diese lästigen Zeilenende-Kommentare loswerden und trotzdem die CRLF-Robustheit beibehalten, indem Sie die
\r
Zeichen entfernen, bevor Sie die Zeilen an die Shell übergeben. Dies stellt etwas mehr Vertrauen in den unberechenbaren Schale (es wäre schön, zu verwenden ,{ tr -d \\r|bash;}
anstatt(tr -d \\r|bash)
aber geschweiften Klammern sind bash-only - Syntax):Dieser Ansatz beeinträchtigt natürlich die Möglichkeit, Standardeingaben in das Skript zu leiten.
quelle