Muscheln mit der Fähigkeit, `\ r` als Leerzeichen zu behandeln

7

Als persönliches Projekt versuche ich, ein Skript zu schreiben, um einige der fremden Dateien zu bereinigen, die im Lieferumfang von Windows 10 enthalten sind, das unter Cygwin ausgeführt wird. Ich möchte, dass das Skript kopiert und eingefügt werden kann, was erfordert, dass es gegenüber verschiedenen Arten von Zeilenumbrüchen robust ist. Gibt es shähnliche Muscheln, die die Fähigkeit zur Behandlung \rals Leerzeichen offenlegen, möglicherweise wenn eine Option festgelegt ist?

Es ist eine seltsame Sache. Die Antwort könnte sich auf "Ja, das ist eine seltsame Sache und es gibt keine Möglichkeit, es zu tun" beschränken.

Gregory Nisbet
quelle
Irgendwas dagegen dos2unixoder einfach alt sed?
Rui F Ribeiro
Ich möchte, dass das Skript "nur ausgeführt" werden kann, ohne dass die Zeilenenden zuerst repariert werden. Es gibt einige Sprachen / Programme wie pythonund perldiese sind zeilenend unempfindlich.
Gregory Nisbet
Möchten Sie eine Shebang-Zeile für ein Skript, das in einer solchen Shell ausgeführt wird, oder nur eine geeignete Shell identifizieren, die direkt aufgerufen werden kann?
Michael Homer
@ MichaelHomer Beide Optionen sind völlig in Ordnung. Soweit ich das beurteilen kann, bashkann es nicht so konfiguriert werden, dass es \randers verarbeitet wird.
Gregory Nisbet

Antworten:

7

Dies ist im Allgemeinen für ein tatsächliches Skript nicht möglich.

  1. Ein eigenständiges ausführbares Skript verfügt über eine Shebang-Zeile, die den zu verwendenden Interpreter identifiziert:

    #!/bin/sh
    

    Das Problem ist, dass unabhängig vom Interpreter die Shebang-Zeile selbst vor dem Ende ein Wagenrücklaufzeichen enthält, was bedeutet, dass der Interpreter nicht gefunden wird (abgesehen von dem unwahrscheinlichen ausführbaren Namen wörtlich $'sh\r'- was unter Windows meiner Meinung nach illegal ist). .

  2. Die andere Art von ausführbarem Skript ist eine Nur-Text-Datei mit gesetztem Ausführungsbit, die POSIX als Skript in der POSIX-Shell-Befehlssprache interpretieren muss (wenn sie von einer kompatiblen Shell selbst aufgerufen wird). Wie Sie jedoch festgestellt haben, behandelt diese Shell-Sprache Wagenrückläufe als Datenbytes, sodass Sie das von Ihnen identifizierte Problem haben.


Sie haben einige Möglichkeiten. Eine besteht darin, direkt auf ein tatsächlich ausführbares Skript zu verzichten und einfach zuerst einen Interpreter für eine andere Sprache aufzurufen. Sie haben Perl und Python identifiziert, und tatsächlich sind die meisten Skriptsprachen mit jedem modernen Zeilenendformat zufrieden. Das Aufrufen des Skripts als perl cleanup.plist kein Problem.

Viele Verwaltungsaufgaben sind in einer herkömmlichen Shell-Sprache jedoch viel einfacher, und es gibt noch einen Trick: Beenden Sie jede Zeile mit einem Kommentar.

echo hello #
rm file.ext #
mv /path/other.fl /path/bin #

Der #Charakter fügt in allen Standard-Shells (in nicht interaktiven Kontexten) einen Kommentar am Ende der Zeile ein. Der Kommentar enthält das Wagenrücklaufbyte, das ein feines Element eines Kommentars ist, und endet unmittelbar danach mit dem abschließenden Zeilenvorschubbyte.

Es ist wichtig, dass vor dem Hash ein Leerzeichen steht: Ein #Inneres eines Wortes beginnt nicht mit einem Kommentar, sondern ist Teil des Wortes .

Sie können dieses Skript direkt mit einer Shell ausführen:

bash cleanup.sh
dash cleanup.sh
sh cleanup.sh

Wenn Sie es jedoch durch Eingabe eines Befehls aus einer vorhandenen Shell-Sitzung starten möchten, funktionieren auch die oben genannten POSIX-Skripte: Machen Sie die Datei einfach ausführbar, und dann

./cleanup.sh

führt es mit dem aus, was Ihre Shell für ein POSIX-Skript für richtig hält .

Da dies wie ein Einzelstück klingt, lohnt es sich wahrscheinlich nicht, es ausführbar zu machen, und sh cleanup.shscheint mir daher nur angemessen zu sein.


Mein ehrlicher Vorschlag für diese Situation ist wahrscheinlich Powershell (oder Batch auf Knopfdruck), aber ich verstehe, dass es nicht das ist, was Sie wollen. WSL ist eine weitere Option: Sie verarbeitet Wagenrückläufe in der Shebang-Zeile automatisch, und für den Rest können Sie Kommentare verwenden.

Michael Homer
quelle
1
Können Sie ein Befehlszeilenargument verwenden, um das zu verbergen / zu essen \r? wie #!/bin/sh -b(Bashs -b" Melde den Status von abgebrochenen Hintergrundjobs sofort und nicht vor der nächsten primären Eingabeaufforderung ", daher ist es für den nicht interaktiven Gebrauch ziemlich harmlos.) Ich habe es nur unter Linux mit -b^Mversucht und Bash sagt : invalid option, also leider nicht. Vielleicht gibt es eine Option, die einen Charakter als Argument verbrauchen kann, ohne zu brechen, wenn er nicht da ist?
Peter Cordes
1
Cygwin ist jedoch funky: Es ist die Cygwin-Bibliothek selbst, die das # analysiert! Zeile, weil das eigentliche Betriebssystem (Windows) es nicht versteht. Es ist eine User-Space-Emulation von POSIX auf einem Nicht-POSIX-Betriebssystem. Theoretisch könnten Sie also einfach eine Version der Cygwin-DLL erstellen, die \rvor der Verarbeitung ein nachfolgendes (falls vorhanden) von einer Shebang-Zeile entfernt, möglicherweise einfacher, als einen benutzerdefinierten Linux-Kernel zu kompilieren, der dasselbe tut . Und Sie müssen den Windows-Kernel nicht ändern (gut, weil er Closed Source ist).
Peter Cordes
1
Aber da Fenster halten \r\ndie übliche Linie endet, soll nicht eine Hash - Bang Linie #!/bin/sh\r\nsucht , /bin/shohne die CR? Dann brauchen Sie nur noch eine richtig fixierte Shell /bin/sh\r. Was unter Unixen funktionieren sollte (solange das Skript nicht versucht, Argumente in der Hashbang-Zeile zu übergeben), obwohl es schrecklich hässlich wäre.
Ilkkachu