:
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 :> file
ist 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 otherfile
in einige benannte Variablen einliest . Der Schleifenkörper echo
druckt sie mit ;
Trennzeichen anstelle der zuvor verwendeten Leerzeichen. file
wird 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 >file
würde weniger lästig sein, und Sie müssen die Datei nicht erst abschneiden. read -r
isst nicht \
als Fluchtcharakter.
Die Textverarbeitung in Bash ist ziemlich langsam. Ein Teil davon ist unvermeidlich: Es read
muss 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 otherfile
Name "albern" lautet --version
.
Wenn Sie das Ausgabefeldtrennzeichen auf festlegen, ;
können Sie nur mehrere Felder als Argumente zum Drucken übergeben. Shell read
weist 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 split
es 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. $5
Wenn 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 , gensub
auf $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 print
wie zuvor, aber mit tail
anstelle 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: > file
stattdessen als lesen .