:ist ein anderer Name für true. Beide sind Shell-Builtins in Bash, aber es gibt keine /bin/:, nur eine /bin/true. Die Ausgabeumleitung bewirkt, dass die Shell open(2)die Datei mit O_CREAT|O_TRUNC. Wenn nichts geschrieben ist, bleibt die Länge Null.
Das Zusammenfügen dieser beiden Teile :> fileist eine gängige Redewendung für das Abschneiden von Dateien. Die meisten Leute würden versuchen, es durch Schreiben weniger komisch aussehen zu lassen : >file.
Da Sie in einem Kommentar zur 2. Zeile gefragt haben, werde ich meine Kommentare in eine Antwort umwandeln. (Auch wenn Sie dies nicht in Ihrer Frage gestellt haben.)
Die 2. Zeile ist eine Schleife, die Zeilen otherfilein einige benannte Variablen einliest . Der Schleifenkörper echodruckt sie mit ;Trennzeichen anstelle der zuvor verwendeten Leerzeichen. filewird bei jeder Iteration geschlossen und erneut geöffnet (zum Anhängen), da sich die Umleitung innerhalb der Schleife befindet. Die Verwendung von while ...;do read -r ...;done <otherfile >filewürde weniger lästig sein, und Sie müssen die Datei nicht erst abschneiden. read -risst nicht \als Fluchtcharakter.
Die Textverarbeitung in Bash ist ziemlich langsam. Ein Teil davon ist unvermeidlich: Es readmuss jeweils ein Byte (ein read(2)Systemaufruf pro Byte) gesendet werden, um ein Überschießen des Zeilenendes zu vermeiden. Es wäre besser, das richtige Werkzeug für den Job zu verwenden:
awk -vOFS=';' '{ print $1, $2, $4, $5, $3 }' -- otherfile >file
--bedeutet, dass Ihr Skript nicht kaputt geht, wenn der otherfileName "albern" lautet --version.
Wenn Sie das Ausgabefeldtrennzeichen auf festlegen, ;können Sie nur mehrere Felder als Argumente zum Drucken übergeben. Shell readweist der letzten Variablen den gesamten Rest der Zeile mit Leerzeichen zu, aber es gibt keine Möglichkeit, awk anzuweisen, nur in 5 aufzuteilen. Perl macht dies einfach, da splites ein Maximum an Feldern haben kann, aber es ist viel langsamer zu starten als awk.
Eigentlich stellte sich heraus, dass es nicht so schwer war, nur einen hässlichen Regex zu schreiben. $5Wenn Sie nicht in awk, sondern in Rest-of-the-Line arbeiten möchten, verlieren Sie beim Überlaufen von Feldern immer noch das ursprüngliche Leerzeichen. Meine erste tragfähige Idee ist , zu verwenden , gensubauf $0(die ganze Zeile) die ersten 4 Felder (dh nicht-Raum , gefolgt von Raum) zu entfernen, so dass alles anderes:
awk -vOFS=';' '{ tail = gensub("[[:space:]]*([^[:space:]]+[[:space:]]+){4}", "", 1); print $1, $2, $4, tail, $3 }' -- otherfile >file
Ich habe es gleich beim ersten Versuch richtig verstanden, aber die Tatsache, dass ich davon beeindruckt war, sagt etwas über die Lesbarkeit dieses awk-Codes aus. >. <
Beachten Sie, wie es das gleiche ist printwie zuvor, aber mit tailanstelle von $5.
echo 'A B c DD e f g f' |
awk -vOFS=\; '{ tail = gensub("[[:space:]]*([^[:space:]]+[[:space:]]+){4}", "", 1);
print $1, $2, $4, tail, $3 }'
A;B;DD;e f g f;c
Dies wäre beeindruckender, wenn ich das Literal kopieren / einfügen und zeigen könnte, dass es in der Ausgabe durchgekommen ist. Tippe eins in bash mit ^ Q. ctrl-Q bedeutet Zitieren Sie den nächsten Tastendruck als wörtliches Zeichen, da die Zeilenbearbeitung im Emacs-Stil von bash mit der von Emacs identisch ist.
http://mywiki.wooledge.org/BashFAQ enthält einige nützliche Informationen zum Thema Skripterstellung, die unabhängig davon, welche Daten oder Dateinamen Sie in das Skript einfügen, keine Probleme verursachen.
:>es sich nicht um einen einzelnen Bediener handelt. Es ist möglicherweise einfacher zu verstehen, wenn Sie es: > filestattdessen als lesen .