Wenn Sie dies tun und die benötigten Leerzeichen entfernen möchten:
echo -n "Hello" | od -A n -t x1 | sed 's/ *//g'
Die ersten beiden Befehle in der Pipeline werden von @TMS in seiner Antwort, bearbeitet von @James, gut erklärt. Der letzte Befehl unterscheidet sich vom @TMS-Kommentar dadurch, dass er sowohl korrekt ist als auch getestet wurde. Die Erklärung lautet:
sed
ist ein s behandeln ed itor.s
ist das s Befehl ersetzen./
öffnet einen regulären Ausdruck - jedes beliebige Zeichen kann verwendet werden./
ist konventionell, aber umständlich für die Verarbeitung von beispielsweise XML oder Pfadnamen./
oder das von Ihnen gewählte Alternativzeichen schließt den regulären Ausdruck und öffnet die Substitutionszeichenfolge.- In
/ */
die*
entspricht einer beliebigen Folge des vorherigen Zeichens (in diesem Fall ein Leerzeichen). /
oder das von Ihnen gewählte alternative Zeichen schließt die Substitutionszeichenfolge. In diesem Fall die Substitutionszeichenfolge//
ist leer, d.h. der Treffer wird gelöscht.g
ist die Option, diese Ersetzung g vorzunehmen global auf jeder Zeile statt nur einmal für jede Zeile.- Die Anführungszeichen verhindern, dass der Befehlsparser verwirrt wird - die gesamte Sequenz wird an
sed
übergeben als erste Option, nämlich einesed
Skript.
@TMS-Gehirnkind (sed 's/^ *//'
) entfernt nur Leerzeichen am Anfang jeder Zeile (^
entspricht dem Anfang der Zeile - 'Musterraum' in sed
-sprechen).
Wenn Sie zusätzlich Zeilenumbrüche entfernen möchten, ist der einfachste Weg das Anhängen
| tr -d '\n'
zu den Befehlspfeifen. Es funktioniert wie folgt:
|
speist den zuvor verarbeiteten Stream in die Standardeingabe dieses Befehls ein.tr
ist das tr anslate-Befehl.-d
gibt das Löschen der Übereinstimmungszeichen an.- Anführungszeichen listen Ihre übereinstimmenden Zeichen auf - in diesem Fall nur Zeilenumbruch (
\n
).Translate passt nur auf einzelne Zeichen, nicht auf Sequenzen.
sed
ist eindeutig verzögert, wenn es um Zeilenumbrüche geht. Das liegt daran, dass sed
ist einer der ältesten unix
Befehle - es wurde erstellt, bevor die Leute wirklich wussten, was sie taten. Allgegenwärtige Legacy-Software verhindert, dass es behoben wird. Ich weiß das, weil ich vor unix
geboren wurde wurde geboren.
Der historische Ursprung des Problems war die Idee, dass ein Zeilenumbruch ein Zeilentrennzeichen und kein Teil der Zeile sei. Es wurde daher von den Zeilenverarbeitungsdienstprogrammen entfernt und von den Ausgabedienstprogrammen wieder eingefügt. Das Problem ist, dass dies Annahmen über die Struktur von Benutzerdaten macht und in vielen Einstellungen unnatürliche Einschränkungen auferlegt. sed
Die Unfähigkeit von , Zeilenumbrüche einfach zu entfernen, ist eines der häufigsten Beispiele für diese missgebildete Ideologie, die Kummer verursacht.
Es ist möglich, Zeilenumbrüche mit sed
zu entfernen - Es ist nur so, dass alle mir bekannten Lösungen sed
ergeben Verarbeiten Sie die gesamte Datei auf einmal, was bei sehr großen Dateien zu Engpässen führt und den Zweck eines Stream-Editors zunichte macht. Jede Lösung, die die Zeilenverarbeitung beibehält, wenn es möglich ist, wäre ein unlesbares Rattennest aus mehreren Pipes.
Wenn Sie darauf bestehen, sed
zu verwenden versuche:
sed -z 's/\n//g'
-z
sagt sed
um Nullen als Zeilentrennzeichen zu verwenden.
Intern ein String in C
wird mit einer Null abgeschlossen. Der -z
Die Option ist auch ein Ergebnis von Legacy und wird als Annehmlichkeit für C
bereitgestellt Programmierer, die vielleicht eine temporäre Datei verwenden möchten, die mit C
gefüllt ist -Strings und aufgeräumt durch Zeilenumbrüche. Sie können dann problemlos jeweils eine Zeichenfolge lesen und verarbeiten. Auch hier erlegen die frühen Annahmen über Anwendungsfälle den Benutzerdaten künstliche Beschränkungen auf.
Wenn Sie den g
weglassen Option entfernt dieser Befehl nur den ersten Zeilenumbruch. Mit dem -z
Option sed
interpretiert die gesamte Datei als eine Zeile (es sei denn, es sind vereinzelte Nullen in der Datei eingebettet), die durch eine Null abgeschlossen werden und daher auch große Dateien verstopfen.
Sie denken vielleicht
sed 's/^/\x00/' | sed -z 's/\n//' | sed 's/\x00//'
könnte funktionieren. Der erste Befehl setzt zeilenweise eine Null an den Anfang jeder Zeile, was zu \n\x00
führt jede Zeile beenden. Der zweite Befehl entfernt einen Zeilenumbruch aus jeder Zeile, die jetzt durch Nullen getrennt ist - aufgrund des ersten Befehls gibt es nur einen Zeilenumbruch. Alles, was übrig bleibt, sind die falschen Nullen. So weit, ist es gut. Die kaputte Idee dabei ist, dass die Pipe den letzten Befehl zeilenweise füttert, da der Stream so aufgebaut wurde. Tatsächlich wird der letzte Befehl, wie geschrieben, nur eine Null entfernen, da jetzt die gesamte Datei keine Zeilenumbrüche hat und daher eine Zeile ist.
Eine einfache Pipe-Implementierung verwendet eine temporäre Zwischendatei, und alle Eingaben werden verarbeitet und in die Datei eingespeist. Der nächste Befehl wird möglicherweise in einem anderen Thread ausgeführt und liest gleichzeitig diese Datei, aber er sieht nur den Stream als Ganzes (wenn auch unvollständig) und hat keine Kenntnis von den Chunk-Grenzen, die die Datei speisen. Selbst wenn die Pipe ein Speicherpuffer ist, sieht der nächste Befehl den Stream als Ganzes. Der Fehler ist untrennbar in sed
eingebrannt .
Damit dieser Ansatz funktioniert, benötigen Sie einen g
Option beim letzten Befehl, also verschluckt es sich wieder bei großen Dateien.
Die Quintessenz lautet:Verwenden Sie sed
nicht um Zeilenumbrüche zu verarbeiten.
echo hello | hexdump -v -e '/1 "%02X "'
echo -n "Hello" | od -A n -t x1
Erklärung:
- Der
echo
Das Programm liefert die Zeichenkette für den nächsten Befehl. - Der
-n
Flag weist Echo an, keine neue Zeile am Ende des „Hallo“ zu erzeugen. - Der
od
Programm ist das "Octal-Dump"-Programm. (Wir werden ein Flag bereitstellen, um es anzuweisen, es im Hexadezimalformat statt im Oktalformat auszugeben.) - Der
-A n
Flag ist die Abkürzung für--address-radix=n
, wobei n die Abkürzung für "none" ist. Ohne diesen Teil würde der Befehl auf der linken Seite ein hässliches numerisches Adresspräfix ausgeben. Dies ist nützlich für große Dumps, aber für einen kurzen String ist es unnötig. - Der
-t x1
Flag ist die Abkürzung für--format=x1
, wobei das x die Abkürzung für "hexadezimal" und die 1 für 1 Byte steht.